ES6中的一些新特性
引入let/const的目的
ES5中的作用域分为:全局作用域 和 函数作用域。
并没有块作用域的概念,ECMAScript 6(简称ES6)中新增了块级作用域。
块作用域由 { }
包括,if
语句和for
语句里面的{ }
也属于块作用域。
ES5创建作用域的两种方式:
- 立即执行函数
try catch
语句
在ES6中引入let/const增加块级作用域的概念,这便于开发者对变量的管理使用,避免变量污染等问题。举个例子:
例子一:
for(var i = 0; i<5;i++){
setTimeout(function(){
console.log(i);
}, 1000)
}
// 上面的代码输出5个5
for(let i = 0; i<5; i++){
setTimeout(()=>{
console.log(i);
}, 2000)
}
// 上面的代码依次输出0,1,2,3,4
let
声明的变量在块级作用域中,但是var
生命的变量在全局作用域下,当执行setTimeout时,全局域下的i
值已经变成5。
例子二:
let a = 1;
console.log(`a is ${a}`);
let a = 2; // Uncaught SyntaxError: Identifier 'a' has already been declared
const b = 'b';
const c; // Uncaught SyntaxError: Missing initializer in const declaration
c = 'c';
用let/const
声明过的变量,不能再次声明,主要是防止变量名滥用,导致相互覆盖。
而用const
声明的变量必须立即赋值,这种限制也符合const本身的意义(不需要二次赋值,因此最好声明的时候赋值,便于维护)。
例子三:
var a = 1;
console.log(window.a); // 1
let b = 1;
console.log(window.b); // undefined
使用let/const
声明的变量不会绑在window对象上面(window对象属于浏览器的部分,故此话针对浏览器端而言)。
解构赋值
解构赋值的出现可以从对象中更加方便快捷地取出需要的数据,避免出现大量很相近的重复代码。
解构赋值本质上利用了ES6的Iterator
特性,只有可以被迭代的对象才可以应用解构赋值,对于null
或undefined
使用结构赋值,程序会抛出异常。
let {a, b} = {a:1, b:'b'};
console.log(a,b); // 1 "b"
let {c} = null; // Uncaught TypeError: Cannot destructure property `c` of 'undefined' or 'null'.
Iterator
遍历器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
具有遍历接口的对象称为可遍历的,可以通过for ... of
语句访问内部成员。
我们知道,在JavaScript中,也可以通过for ... in
语句遍历对象属性, 那么 for ... of
和 for ... in
有什么区别么?
let arr = ['a', 'b'];
arr.name = 'array';
for(let k in arr){
console.log(arr[k]);
}
// 'a' 'b' 'array'
for( let k of arr){
console.log(k);
}
// 'a' 'b'
通过上面代码发现,for ... of
语句并没有遍历到 数组arr 的name
属性。
ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator属性,或者说,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)。
原生具备 Iterator 接口的数据结构如下:
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
另外,在ES6中,跟Iterator
特性密切相关是Geneator
。后面有机会再详细展开。