ECMAScript 6新增功能——块级作用域与解构赋值
根据ECMAScript 6入门学习了ES6的一些新特性,在io.js v1.61版本进行代码测试,部分代码需要打开了--harmony,--use_strict等flag。
这个系列将将会有如下内容
- let , const以及块级作用域
 - 变量的解构赋值
 - 新增的方法
 - Set和Map数据结构
 - Generator函数
 - Promise对象
 - Class和Module
 
let , const以及块级作用域
注:以下代码需要io.js —harmony —use_strict
使用let声明的变量仅在所处的代码块中有效,即该变量处于块级作用域。
1  | {  | 
用let声明的变量不存在变量提升,也不允许在代码块中出现相同的声明,即使在let声明之前。
1  | function() {  | 
使用let声明的变量将绑定其块级作用域,(这边不是特别清晰)可以避免在循环中声明函数时出现的隐患:1
2
3
4
5for(let i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);  // 输出为0-9
    });
}
如果上面的例子中改为var声明,则会输出10个10。
const拥有和let同样的特点,并且它用于声明常量,尝试改变常量的值不会导致异常,只会默默失败。1
2
3const a = 6;
a = 3;
console.log(a);  // 6
用const声明的对象仅是让其对象的引用地址保持不变,无法保证其属性不发生改变,要让对象不被改变,可以在使用const声明的同时,调用方法Object.freeze:1
const a = Object.freeze({ msg: "Hello world!" });
在ES6中,函数声明时的作用域在其所处的块级作用域内。1
2
3
4
5
6
7
8
9function f() { console.log('I am outside!'); }
(function () {
  if(false) {
    // 重复声明一次函数f
    function f() { console.log('I am inside!'); }
  }
 
  f();  // ES5中,由于函数声明提升,输出为'I am inside!',但在ES6中,结果为'I am outside!'
}());
最后,在ES6中规定,在全局使用var或是function声明的变量都会作为全局对象的属性,但用let , const或是class声明的变量,将不会成为全局对象的属性。(这边补充下,在node.js/io.js环境下,一个模块中全局声明的变量是不会成为全局对象global的属性的,要成为其属性,需要显式地赋值)1
2
3
4var a = 6;
console.log(window.a);  // 6
let b = 3;
consoel.log(window.b);  // undefined
变量的解构赋值(Destructure)
注:当前版本的io.js不支持destructure
有两种解构赋值方式:数组解构和对象结构1
2
3
4
5var [foo, bar] = [1, 3];  // foo = 1, bar = 3
var [foo, [bar]] = [1, [3]];  // foo = 1, bar = 3
var [,,third] = ["foo","bar","baz"];  // third = "baz"
var [head, ...tail] = [1,2,3,4]; // head = 1, tail = [2, 3, 4] (array spread特性)
var [a,b] = [1]; // a = 1, b = undefined
简单地说就是等号两边的模式匹配,如果匹配不成功,则变量值为undefined。对于数组解构,要求的是结构和顺序的匹配,而对于对象解构,要求的是结构和属性名的匹配:1
var {foo, bar} = { foo: 'aaa', bzz: 'zzz' } // foo = 'aaa', bzz = undefined
如果变量名和属性名不一样也需要解构赋值,可以这样写:1
var { foo: baz } = { foo: 'aaa' };  // baz = 'aaa'
两种解构赋值的方式都可以使用默认值:1
2var [a, b=3] = [6];  // a = 6, b = 3
var {foo,bar="dog"} = {};  // foo = undefined, bar = "dog"
用途:(这部分照抄了原文,觉得很有道理,不过鉴于io.js暂时不支持该特性,并未实践过如下用途)
交换变量的值1
[x, y] = [y, x]
函数返回多个值1
2
3
4
5
6
7
8
9
10
11
12
13
14// 返回一个数组
function example() {
    return [1, 2, 3];
}
var [a, b, c] = example();
// 返回一个对象
function example() {
  return {
    foo: 1,
    bar: 2
  };
}
var { foo, bar } = example();
函数参数的定义及设置默认值(合并了原文中的3和4)1
2
3
4
5
6
7
8
9
10jQuery.ajax = function (url, {
    async = true,
    beforeSend = function () {},
    cache = true,
    complete = function () {},
    crossDomain = false,
    global = true
    }) {
        // ... do stuff
    };
遍历Map结构1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16var map = new Map();
map.set('first', 'hello');
map.set('second', 'world');
for (let [key, value] of map) {
   console.log(key + " is " + value);
}
// 获取键名
for (let [key] of map) {
  // ...
} 
// 获取键值
for (let [,value] of map) {
  // ...
}