ECMAScript6 和 let、const
1. ES6简介
npm install -g es-checker //查询本机对ES6的支持程度
es-checker
2. let命令
- 基本用法
let声明的变量只在其命令所在的代码块内有效。
for循环设置循环变量的那部分是一个父作用域,而循环体内部是一个单独作用域。
- 不存在变量提升
let声明的变量一定要在声明后使用
- 暂时性死区
若块级作用域存在let命令,它所声明的变量就绑定在这个区域,不受外部影响。
区块中存在let和const命令,这个区块对这些命令声明的变量从一开始就形成封闭作用域。只要在声明之前使用这些变量,就会报错。
在let命令声明变量xx之前,都属于变量xx的 “死区”。
//分析:x=y,在x赋值为y时,y还没有定义
function bar(x=y,y=2){}
bar(); //报错
//分析:由于y赋值为x时,x已经定义且为2
function bar(x=2,y=x){}
bar(); //成功
暂时性死区的本质,只要进入当前作用域,所有使用的变量就已经存在,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
- 不允许重复声明
let不允许在相同作用域内重复声明同一个变量。
区块中存在let和const命令,这个区块对这些命令声明的变量从一开始就形成封闭作用 域。只要在声明之前使用这些变量,就会报错。
3. 块级作用域
为什么需要块级作用域内层变量可能会覆盖外层变量(即使if里的a访问不到,但var的存在同样会出现问题)
var a = 1;
function f(){
console.log(a);
if(false){
var a = 'xxx'
}
}
f() // undefined
用来计数的循环变量i会泄露为全局变量
- ES6的块级作用域
外层作用域无法读取内层作用域的变量
内层作用域可以定义外层作用域的同名变量
块级作用域的出现可以把ES5里的匿名函数取代了。
- 块级作用域和函数声明
在ES5中,在if内声明的函数f会被提升到函数头部
在ES6中,块级作用域内声明的函数类似于let,对作用域之外没有影响
应该避免在块级作用域内声明函数,如果确实需要,也应该写成函数表达的形式
ES6的块级作用域允许声明函数的规则只在使用大括号的情况下成立,没大括号就报错
if(true){
function f(){} //成功
}
if(true)
function f() {} //失败
- do表达式
在块级作用域之前加上do,使得块级作用域可以变为表达式,即可以返回值
4. const命令
- 基本用法
const声明一个只读的常量,且不可改变值。const一旦声明常量,必须立即初始化
const的作用域与let相同,只在声明所在的块级作用域内有效
- 本质
const实际上保证的并不是变量的值不得改动,而是变量指向的地址不能改动
在对象/数组里,不可变的是地址,但对象本身可变,可以为其添加新属性
const foo = {}
foo.prop = 123; //成功
foo = {}; //失败
将对象冻结方法,对象的属性也冻结
const foo = Object.freeze({}); //对象冻结
var constantize = (obj) => {
Object.freeze(obj);//对象冻结
Object.keys(obj).forEach( (key) => { //属性冻结
if( typeof obj[key] == 'object'){
constantize(obj[key]);
}
})
}
以上两个方法的解析:
Object.keys(obj); //获取obj中所有可读出来的键,组成个数组
Array.proprototy.forEach(function(currentValue,index){
doSomething(currentValue);
}) //对数组的所有元素,执行一次给定的函数 (index为索引非必须)
- ES6声明变量
var function let const import class
5. 顶层对象的属性
ES5中,顶层对象的属性与全局变量等价
ES6中,var 和 function命令声明的全局变量依旧全局;let、const 和 class声明的不属于顶层对象的属性
6. global对象
浏览器,顶层对象是 window;
浏览器 + Web Worker,顶层对象是 self;
Node,顶层对象是 global
在全局环境中,this返回顶层对象,ES6中,this返回的是当前模块
函数中的this,若是对象中的方法 ++this指向该对象;若是单纯函数运行 this指向顶层对象