1

前言

工作中使用ES6开发项目已经很长时间了,趁现在不忙,将ES6的知识点梳理一遍。一为查漏补缺,二为加深记忆。

letconst命令

let命令的特点

1.不存在变量提升:即必选先声明后使用,否则报错
2.只在代码块中有效
3.暂时性死区
4.不允许重复声明


1、不存在变量提示

在ES5中,使用var声明的变量,在脚本开始运行时,变量已经存在,只不过值为undefined。

console.log(v); //undefined
var v = 'exit';

而let声明的变量,必须先声明后使用,否则会报错。

console.log(v); //ReferenceError: v is not defined
let v = 1;

2、只在块级作用域中有效

在代码快中,let声明的变量,在该代码块之外是无法访问的。

{
    let a = 1;
    var b = 2;
}
console.log(a); // ReferenceError a is not defined
console.log(b); // 2

一个常用的let技巧是配合for循环,如下代码所示:

for(let i = 0; i<10; i++){}
console.log(i); // Reference is not defined

3、暂时性死区(temporal dead zone, TDZ)

ES6规定,如果一个作用域中存在let或const命令声明的变量,这个作用域针对这些变量形成了封闭作用域,必须在该作用域中先声明后使用。封闭作用域的意思是指,同样名字的全局变量,将在这里无效。如下代码所示,

// global 
let a = 1;
{
    console.log(a); // ReferenceError a is not defined
    let a = 2;
    console.log(a); // 2
}

下面是一个比较隐蔽的暂时性死区

function bar(x = y, y=2) {
    // ES6的默认参数,也是相当于在用let声明了x与y一句, let x = y;
  return x + y
}
bar(); //ReferenceError y is not defined

4、(同一作用域内)不允许重复声明

跟var有区别的是var可以对一个变量重复声明,但是在同一个作用域中,let重复声明同一个变量会导致错误。

let a; 
let a; //SyntaxError:Identifier 'a' has already been declared

Q1: 块级作用域是如何定义的?
A1:
Q2: 为什么需要块级作用域?

A2:在ES5中只有全局作用域,与函数作用域(也就是内部作用域),但是这通常会导致两个问题:

1.内部变量可能会覆盖外部变量:

let tem = new Date();
function foo() {
    // 变量提示导致tem被覆盖
    console.log(tem);
    if(false){
        //即便这里不会执行,function作用域内变量会存在提升的情况
        var tem = 2;
    }
}
foo(); //输出undefined

2.用来计数的循环变量泄露为全局变量

for(var i =0; i< 10; i++){
}
console.log(i); // 10

块级作用域出现之前,经常使用IIFE来处理私有变量的问题,避免别的代码修改到某个变量。
而块级作用域的出现,实际上使得广泛应用的立即执行函数表达式IIFE不再需要了。

const命令的特点

  1. 声明常量
  2. const 声明的常量是引用类型的值时,const保存的只是引用的地址,但是不能保证引用类型的值不能改变
const obj = {};
// 有效
obj.a = 1;
obj = {}; //error 不能将obj指向两个内存地址

顶层对象的属性与全局对象属性

ES6规定:1:var function关键字声明的全局变量,依旧是顶层对象的属性。2:let const class命令声明的全局变量,不属于顶层对象的属性。
也就是说从ES6开始,全局变量属性将逐步与顶层对象的属性脱钩。

// 全局作用域
var a = 1;
console.log(window.a); //1

let b = 2;
console.log(window.b); //undefined

luckybo
182 声望26 粉丝

引用和评论

0 条评论