块级作用域
es6中let和const形成了一个块级作用域,他们声明的变量只存在块内。块级作用域外是不能访问内部声明的变量的。
{
let a = 10
}
a //ReferenceError
{
var a = 10
}
a //10
内层作用域可以定义外层作用域的同名变量,例如
function foo() {
let n = 5;
if (true) {
let n = 10
}
console.log(n); // 5
}
外层代码块不受内层代码块的影响
块级作用域是可以无限嵌套的
块级作用域的作用:
1.内层变量不会影响外层变量,因为es5中只有全局作用域和函数作用域,这样会导致内层变量修改外层变量的值。
2.循环中用来计数的局部变量不会泄露成全局变量。
let const var
let 和 const 只可以先定义后使用,不存在变量提升,代码块中只要有let 或 const, 它所声明的变量就“绑定”在这个区块内,不受外部影响。
for 循环 会形成两层的作用域区块,循环语句部分是一个父作用域,循环体内部是一个单独的子作用域。例如
for(let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i); //输出3次abc
}
暂时性死区
for (let i = 0; i < 3; i++) {
console.log(i); //Uncaught ReferenceError: i is not defined 因为后面有使用let重新定义i, i在这里被绑定了一个死区
let i = 'abc';
console.log(i);
}
{
typeof x; //Uncaught ReferenceError: x is not defined 因为后面有使用let重新定义x, let x之前都是x的死区
let x; // 然而要是没有let x, typeof x 返回的则是undefined
}
暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,不可使用。只有等到声明变量的那一行代码出现,才可以获取或者使用。
let不允许在相同作用域内,重复声明同一个变量。
var
var 定义的变量挂载在函数作用域或者全局作用域上。当var声明了一个变量,这个变量就有一个存储空间,初始化值为undefined,当执行的范围到达声明出,变量设置为指定的值,如果没有赋值,那么还是undefined.
let定义的变量,就有一个块作用域,也具有一个存储空间,只不过没有初始值,获取或者设置一个未初始化的变量,就得到一个ReferenceError, 当执行到声明的变量处,如果没有赋值的话,变量的值就被初始化为undefined
const
const用来声明一个常量
const声明的变量工作类似let, 但是const必须要有一个初始值。
const foo;
// SyntaxError: Missing initializer in const declaration
const实际上保证的不是变量的值不可改变,而是变量指向的内存地址不得改变。所以如果是简单类型的数据(数值,布尔值,字符串)即值引用类型,是不能改变的。因为它的值就保存在变量指向的内存地址中。如果const声明的是复合类型数据(数组,对象)即地址引用类型,那么它只能保证这个指针是固定不变的,至于它指向的数据结构是不是可变的,就不能控制了。
const foo = {};
// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123
// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only
const a = [];
a.push('Hello'); // 可执行
a.length = 0; // 可执行
a = ['Dave']; // 报错
转载于:https://my.oschina.net/jjjing/blog/879818