ES6学习笔记
let 和 const 命令
1、for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
上面代码正确运行,输出了 3 次abc。这表明函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。
2、ES5 只有全局作用域和函数作用域,没有块级作用域,ES6有块级作用域
if(){}和{}都属于块级作用域
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';
}
}
f(); // undefined
在ES5中会报错,ES5中函数内属于同一作用域
3、let是var的语法糖,本质上还是var,会有编译和提升,我猜es6底层是强制判定在执行let代码之前的变量都是未定义,所以下面代码才会出现报错,而不是按作用域链去父作用域找tmp值
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
var tmp = 123;
if (true) {
tmp = 'abc'; // 不会报错
}
4、const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。如果真的想将对象冻结,应该使用Object.freeze方法。
const foo = Object.freeze({});
5、var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性
var a = 1;
// 如果在 Node 的 REPL 环境,可以写成 global.a
// 或者采用通用方法,写成 this.a
window.a // 1
let b = 1;
window.b // undefined