var,let 与 const
- var 申明变量。
- let 申明变量,更完美的 var。
- const 申明常量(物理指针不可以更改的变量)。
在新的 javascript 规范 ES6 中,新增了 let 和 const 命令,let 用来声明变量,const 用来声明常量,用法类似于 var,但不同的是 let/const 所声明的变量/常量,只在当前代码块内有效。
什么是代码块?可以简单地理解为包在 {} 内的代码,看下面这个例子:
{
// console.log(a); // undefined
// console.log(b); // can't access lexical declaration `b' before initialization
// console.log(c); // c is not defined
var a = 1;
let b = 2;
const c = 3;
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
};
// console.log(a); // 1
// console.log(b); // b is not defined
// console.log(c); // c is not defined
通过上面的代码可以看出,只有 let 存在变量提升,代码块中 var a; 被提升到上边,所以可以打印出 undefined。
在代码块外,只有通过 var 申明的 a 可以打印出来,其他都是“is not defined”。
所以目前可以得出两个结论:
- let 和 const 不会提升变量/常量。
- let 和 const 声明的变量/常量只在当前代码块内有效。
一、let
现在已经知道 let 声明变量,变量不会提升,那么在 for 循环中呢?看下面这个例子:
var arr = [];
for (var i = 0; i < 5; i++) {
arr.push(function() {
console.log(i);
});
};
console.log(arr);
// 0: function ()
// 1: function ()
// 2: function ()
// 3: function ()
// 4: function ()
console.log(i); // 5
arr[0](); // 5
arr[1](); // 5
arr[2](); // 5
arr[3](); // 5
为什么打印结果都是5?先打印一下 arr,可以看到是5个 function ()。
所以在 for 循环中每次做的事情就是向 arr 中添加一个打印 i 的方法,但是函数并没有立刻执行,而这个 i 是通过 var i 来声明的,也就是说我们在 for 循环外部也是可以访问到的,在 for 循环外部打印 i,可以看到它的值就是5,所以当去执行函数的时候,打印的都是 5。
下面我们用 ES5 的闭包来修改一下代码:
var arr = [];
for (var i = 0; i < 5; i++) {
arr.push((
function(a) {
return function() {
console.log(a);
};
}
)(i));
};
arr[0](); // 0
arr[1](); // 1
arr[2](); // 2
arr[3](); // 3
这回的打印结果就是每次循环中的 i 值。
再用 ES6 的方式来修改一下代码:
var arr = [];
for (let i = 0; i < 5; i++) {
arr.push(function() {
console.log(i);
});
console.log(i);
};
// console.log(i); // i is not defined
arr[0](); // 0
arr[1](); // 1
arr[2](); // 2
arr[3](); // 3
发现只是将第一段代码的 var 改为了 let,同样打印结果就是每次循环中的 i 值。
这里需要注意一个问题,就是 let i = 0; 声明的位置,是在 for 的 () 内,那么就可以理解成,在 for 内部就定义了一个 i,并且使用 let 声明的,在 for 的外部是访问不到的,所以每次循环就相当于在当前循环的 i 值的前提下向数组 push 的。
二、const
const 除了不能改变物理指针的特性,其他特性与 let 相同。
1、当声明普通数据类型的时候,一旦声明了,就不可以再改变。
let a = 1;
console.log(a); // 1
a = 2;
console.log(a); // 2
const a = 1;
a = 2; // invalid assignment to const `a'
使用 let 声明变量的时候,再次赋值,值可以改变,但使用 const 声明时,无论是否打印结果,都会报错“invalid assignment to const `a'”无效赋值。
2、当声明复杂数据类型的时候,物理指针不可以改变,但可以改变数据内的属性值,并且可以给数据添加新属性。
看下边例子:
let obj1 = {
name: "liu"
};
obj1 = {
age: "24"
};
console.log(obj1); // Object { age: "24" }
obj1.age = "28";
console.log(obj1); // Object { age: "28" }
obj1.sex = "man";
console.log(obj1); // Object { age: "28", sex: "man" }
const obj2 = {
name: "liu"
};
// obj2 = { // invalid assignment to const `obj2'
// age: "24"
// };
obj2.name = "Zhao";
obj2.age = 18;
console.log(obj2); // Object { name: "Zhao", age: 18 }
三、补充
不知道你有没有发现,以上代码在火狐、谷歌、360急速浏览器下都正常运行,但是在 360兼容模式(包括 IE11 兼容模式)下,ES6 语法的 javascript 代码就会报错。
如果有了解过 Node.js 同学,那你应该会知道如果用 ES6 的语法创建一个 Node.js 服务器,无论什么版本的浏览器都不会报错的,那是因为 Node.js 代码是只运行在 Chrome v8 平台上,其对 ES6 的兼容性还是不错的,并且只运行在服务器端,所以不用考虑其他兼容性。
网友评论