var let const
2018-03-17 19:50
211 查看
首先我们比较一下使用var声明的变量和不使用var声明的变量的区别:
使用var声明的变量声明前调用,那么该变量的值为undefined;不使用var声明的变量声明前调用直接报错Uncaught ReferenceError:xxx is not difined;
使用var声明的变量不可delete,不使用var声明则可以delete掉释放空间。(实则浏览器的垃圾回收机制也会清理掉用var声明但是不再使用的的变量,比如某个仅执行一次的函数中被调用的某个var 声明的变量)
未使用var声明的变量实际上是window的一个对象,而使用var声明的变量只是一个本地变量而已。
在使用'use strict'的模式之下,不使用var 声明变量的语法是不被允许的,报错:Uncaugth SyntaxError;
[javascript] view plain copyconsole.log(a); //undefined,这里还涉及<span style="color:#ff0000;">变量提升</span>的概念
console.log(b); //报错 Uncaught ReferenceError: b is not defined
var a = 1;
b = 2;
console.log(a); //1
console.log(b); //2
console.log(window.a); //1
console.log(window.b); //2
delete a;
delete b;
console.log(a); //1
console.log(b); //报错 Uncaught ReferenceError: b is not defined,可见b在声明前使用和声明后delete再使用是一样的结果
再来看下let,var,const声明的变量的区别:看意思就知道,const是常量的意思,就是说只能被定义一次,且不可再改变,否则就会报错:Uncaught TypeError: Assignment to constant variable.另外声明前使用也会报错:Uncaught ReferenceError: a is not defined;看一个例子:[javascript] view plain copyconst foo = {};
foo.prop = 123;
console.log(foo.prop); //123
foo.prop = 456;
console.log(foo.prop); //456
const foo = {}; //Identifier 'foo' has already been declared
这里const定义一个foo之后,对其添加了属性prop,随后又对该属性进行了修改,为什么没有报错?那是因为常量foo本身存储的是一个地址,该地址指向一个对象,不可变的是foo这个地址,即不能把foo指向另一个地址,但对象本身是可变的,所以依然可以为foo添加新属性,改变新属性值,而最后一行中尝试改变foo的地址,就会报错,如果要彻底将对象冻结,应该使用Object.freeze(obj)方法。同理,数组也是一样的:[javascript] view plain copyconst group = [];
group.push('Bob');
console.log(group[0]); //Bob
group = ["Tom"];//Uncaught TypeError: Assignment to constant variable.
var 和 let 就有意思了,let声明的变量声明前使用也会报错,这个与const一致;最重要的一点是let声明了一个块级作用域的变量在一个块的“}”结束的时候,该变量消失。例子:[javascript] view plain copy(function(x,y){
var b = x;
let c = y;
if (true) {
var b = 5;
let c = 6;
console.log(b); //5
console.log(c); //6,这里的let c在下一行的"}"之后消失
}
console.log(b); //5
console.log(c); //3 ,这里仍然是第三行的let c;
}(2,3));
再看一个例子:[javascript] view plain copyvar array1 = [],array2 = [];
for(var i=0;i<10;i++){
array1[i] = function(){
console.log(i);
};
}
for(let j=0;j<10;j++){
array2[j] = function(){
console.log(j);
};
}
array1[6](); //10
array2[6](); //6
所以说let是一个比较保守的变量。这里变量为i的for循环中,i是一个全局变量,array1[i]是一个console.log(i)的函数,而i的最终结果为10,故而每次调用array1[i],实际上都是console.log(10);而let作为仅在其代码块有效的变量,当前的j仅在本轮的循环中有效,就是说每一次循环,j其实都是一个新产生的变量。所以let变量适合用于循环体中。
再看一个例子:[javascript] view plain copyvar tmp = 1;
if(true){
tmp = 2; //ReferenceError
let tmp;
}
这个例子中tmp=2的赋值会报错,因为if中的let对tmp变量的声明,导致该tmp绑定了这个作用域,而let不会像var那样“变量提升”,所以未声明赋值会报错。ES6中明确规定:如果区块中存在let和const命令,则这个区块对这些命令声明的变量从一开始就形成了封闭做作用域,只要在声明之前做任何使用,都会报错。这在语法上称为“暂时性死区”(temporal dead zone ,简称TDZ)。
还有一点要注意,var声明的变量为全局变量,而let,const声明的变量不为全局变量,使用window访问不到,如下:[javascript] view plain copyvar a = 1;
console.log(window.a); //1
let b = 2;
console.log(window.b) //undefined
使用var声明的变量声明前调用,那么该变量的值为undefined;不使用var声明的变量声明前调用直接报错Uncaught ReferenceError:xxx is not difined;
使用var声明的变量不可delete,不使用var声明则可以delete掉释放空间。(实则浏览器的垃圾回收机制也会清理掉用var声明但是不再使用的的变量,比如某个仅执行一次的函数中被调用的某个var 声明的变量)
未使用var声明的变量实际上是window的一个对象,而使用var声明的变量只是一个本地变量而已。
在使用'use strict'的模式之下,不使用var 声明变量的语法是不被允许的,报错:Uncaugth SyntaxError;
[javascript] view plain copyconsole.log(a); //undefined,这里还涉及<span style="color:#ff0000;">变量提升</span>的概念
console.log(b); //报错 Uncaught ReferenceError: b is not defined
var a = 1;
b = 2;
console.log(a); //1
console.log(b); //2
console.log(window.a); //1
console.log(window.b); //2
delete a;
delete b;
console.log(a); //1
console.log(b); //报错 Uncaught ReferenceError: b is not defined,可见b在声明前使用和声明后delete再使用是一样的结果
再来看下let,var,const声明的变量的区别:看意思就知道,const是常量的意思,就是说只能被定义一次,且不可再改变,否则就会报错:Uncaught TypeError: Assignment to constant variable.另外声明前使用也会报错:Uncaught ReferenceError: a is not defined;看一个例子:[javascript] view plain copyconst foo = {};
foo.prop = 123;
console.log(foo.prop); //123
foo.prop = 456;
console.log(foo.prop); //456
const foo = {}; //Identifier 'foo' has already been declared
这里const定义一个foo之后,对其添加了属性prop,随后又对该属性进行了修改,为什么没有报错?那是因为常量foo本身存储的是一个地址,该地址指向一个对象,不可变的是foo这个地址,即不能把foo指向另一个地址,但对象本身是可变的,所以依然可以为foo添加新属性,改变新属性值,而最后一行中尝试改变foo的地址,就会报错,如果要彻底将对象冻结,应该使用Object.freeze(obj)方法。同理,数组也是一样的:[javascript] view plain copyconst group = [];
group.push('Bob');
console.log(group[0]); //Bob
group = ["Tom"];//Uncaught TypeError: Assignment to constant variable.
var 和 let 就有意思了,let声明的变量声明前使用也会报错,这个与const一致;最重要的一点是let声明了一个块级作用域的变量在一个块的“}”结束的时候,该变量消失。例子:[javascript] view plain copy(function(x,y){
var b = x;
let c = y;
if (true) {
var b = 5;
let c = 6;
console.log(b); //5
console.log(c); //6,这里的let c在下一行的"}"之后消失
}
console.log(b); //5
console.log(c); //3 ,这里仍然是第三行的let c;
}(2,3));
再看一个例子:[javascript] view plain copyvar array1 = [],array2 = [];
for(var i=0;i<10;i++){
array1[i] = function(){
console.log(i);
};
}
for(let j=0;j<10;j++){
array2[j] = function(){
console.log(j);
};
}
array1[6](); //10
array2[6](); //6
所以说let是一个比较保守的变量。这里变量为i的for循环中,i是一个全局变量,array1[i]是一个console.log(i)的函数,而i的最终结果为10,故而每次调用array1[i],实际上都是console.log(10);而let作为仅在其代码块有效的变量,当前的j仅在本轮的循环中有效,就是说每一次循环,j其实都是一个新产生的变量。所以let变量适合用于循环体中。
再看一个例子:[javascript] view plain copyvar tmp = 1;
if(true){
tmp = 2; //ReferenceError
let tmp;
}
这个例子中tmp=2的赋值会报错,因为if中的let对tmp变量的声明,导致该tmp绑定了这个作用域,而let不会像var那样“变量提升”,所以未声明赋值会报错。ES6中明确规定:如果区块中存在let和const命令,则这个区块对这些命令声明的变量从一开始就形成了封闭做作用域,只要在声明之前做任何使用,都会报错。这在语法上称为“暂时性死区”(temporal dead zone ,简称TDZ)。
还有一点要注意,var声明的变量为全局变量,而let,const声明的变量不为全局变量,使用window访问不到,如下:[javascript] view plain copyvar a = 1;
console.log(window.a); //1
let b = 2;
console.log(window.b) //undefined
相关文章推荐
- 有趣的JavaScript(一)---let、const与var命令的区别
- var、let、const 区别?
- 变量声明关键字var、let、const
- js中三种定义变量 const, var, let 的区别
- var、let、const 的一些区别
- JavaScript变量声明var,let.const及区别浅析
- JavaScript中var、const、let的区别。
- var let const的区别是什么?
- var、let和const的区别?
- js中const,var,let的区别
- javascript var let const 区别
- var,let,const,function声明的「创建、初始化和赋值」过程
- let var和const
- let var const
- javascript中的var,let和const
- js变量中有var定义和无var定义的区别,es6中let命令和const命令
- 深入理解ES6之var,let,const区别
- var与ES6中const、let声明的变量的区别
- let、var、const的区别
- let,const,var的区别