系列文章 -- ES6笔记系列html
咱们都知道,在ES6之前,JS只有函数级做用域,没有块级做用域这个概念闭包
没有块级做用域,有利有弊,利于方便自由,弊于做用域内的变量容易被共享,例如这个例子函数
var a = []; for (var i = 1; i <= 10; ++i) { a[i] = function() { return i; }; } a[3]() // 11
循环中变量i是处于全局做用域下的,其实这里是个闭包,函数内部的i与函数外的i造成了引用的关系,致使函数退出以后i未被销毁,引用的依然是全局的ispa
循环完成,此时i已是11,调用之,则值皆为11code
这是没有块级做用域支持的经典例子,ES6则引入了这个特性,经过let关键字,造成“块级的做用域”htm
let和var相似,用来声明变量,那么,把上方中的var换成let对象
var a = []; for (let i = 1; i <= 10; ++i) { a[i] = function() { return i; }; } a[3]() // 3
这是正确的结果,由于let使for循环变成了一个“块级做用域”,相似的还有if、while的“块级做用域”blog
if (1) { let a = 10; var b = 11; } console.log(a); // undefined console.log(b); // 11
1)不能重复声明,var重复声明会被覆盖,但let重复声明会报错内存
var aa = 1; var aa = 2; let bb = 1; let bb = 2; // Uncaught SyntaxError: Identifier 'bb' has already been declared
2)不存在变量提高,以下作法会报错作用域
console.log(a2); // Uncaught ReferenceError: a2 is not defined console.log(b); // undefined let a2 = 10; var b = 11;
3) 存在暂时性死区(temporal dead zone),只要块级做用域内存在let的声明,它所声明的变量就“绑定”(binding)这个区域,再也不受外部的影响
var a3 = 3; if (1) { a3 = 1; // Uncaught ReferenceError: a3 is not defined let a3; }
此外,不单是显示的let才存在死区这种状态,在函数的默认参数之中也会发生,以下的b未声明则直接使用a = b会报错
function bar(a = b, b = 2) { return [a, b]; } bar(); // Uncaught ReferenceError: b is not defined
4)let与window对象脱钩
通常来讲,全局var声明的变量,会挂钩在window对象上,但let却不会这样,如
var aa = 1; let bb = 1; console.log(window.aa); console.log(window.bb);
1)匿名函数
没有块级做用域以前,为了整合代码,更好的分块不予外部代码混淆,咱们经常使用匿名函数的自执行方式
(function() { console.log(1); // 1 })();
但或许如今再也不须要了,直接使用一对(或多对)大括号,就有了块级的做用域
{ console.log(1); // 1 }
const声明了一个只读的常量,常量,即值不可更改。
const MAX = 10; MAX = 11; // Uncaught TypeError: Assignment to constant variable.
const除了拥有let上述的特色以外,还有一些要注意的点
1)const一旦声明变量,就必须当即初始化,不然报错
const MAX; // Uncaught SyntaxError: Missing initializer in const declaration
2) const声明的引用类型
const声明的引用类型,只是引用类型的地址不能更改,但其指向的值是能够的,如
const obj = { a: 10 }; obj.a = 11; obj.a // 11