let
{
let a = 10;
var b = 1;
for(var i =1;i<3;i++){
console.log(b+'_$$_'+a);//ok
}
console.log(b+'_&&_'+a);//ok
}
console.log(b+'__'+a);//b是ok,a报错
适用于for循环中
for (let i = 0; i < 10; i++) {
console.log(i);//ok
}
console.log(i);//报错
不存在变量提升
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;
// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
var tmp = 123;
if (true) {
tmp = 'abc'; // 报错滴
let tmp;
}
隐藏死区
function bar(x = y, y = 2) {
return [x, y];
}
bar(); // 报错
不允许重复声明
// 报错
function func() {
let a = 10;
var a = 1;
}
// 报错
function func() {
let a = 10;
let a = 1;
}
function func(arg) {
let arg; // 报错
}
块级作用域
设置块级作用域的原因
1.内层变量可能会覆盖外层变量。
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';//
}
}
f(); // undefined
原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。
2.用来计数的循环变量泄露为全局变量
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}
console.log(i); // 5全局泄露
【es6】
内层作用域可以定义外层作用域的同名变量。同时外层作用域无法读取内层作用域的变量,perfect~~
function f1() {
let n = 5;
if (true) {
let n = 10;
console.log(n); // 10
}
console.log(n); // 5
}
f1();
块级作用域内声明的函数因为环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。
// 函数声明语句
{
let a = 'secret';
function f() {
return a;
}
}
f();//报错
-------------------------------------------------
// 函数表达式
{
let a = 'secret';
let f = function () {
return a;
};
}
f();//a
const
1.const声明一个只读的常量
const PI = 3.1415;
PI // 3.1415
PI = 3;//报错
const foo;//只定义不赋值,报错
其他定义变量会提前,暂时性死区等,声明之前就调用结果报错这那啥的,都和let是一样的
【注意】
当const声明一个对象变量,不可变的只是这个地址,即不能把指针指向另一个地址,但对象本身是可变的
const a = {name:'jack'};
a.name = 'lily'; // 可执行
console.log(a.name);//lily
------------------------------------------------------
如果你想完全不可变:
const a = Object.freeze({name:'jack'});
// 常规模式时,下面一行不起作用;
// 严格模式时,该行会报错
a.name = 'lily';
console.log(a.name);//jack
顶层对象的属性
window对象(顶层对象)有实体含义,指的是浏览器的窗口对象,顶层对象是一个有实体含义的对象。而在es5中顶层对象的属性与全局变量挂钩,程序员很容易不知不觉地就创建了全局变量(比如打字出错);最后,顶层对象的属性是到处可以读写的,这非常不利于模块化编程
window.a = 1;//顶层变量
a // 1全局变量
所以在es6中规定,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。
var a = 1;
// 如果在 Node 的 REPL 环境,可以写成 global.a
// 或者采用通用方法,写成 this.a
window.a // 1
let b = 1;
window.b // undefined
变量的解构赋值
先来看它的用途:
(1)交换变量的值
let x = 1;
let y = 2;
[x, y] = [y, x];