JS篇 ES6新特性

注意:

1. Node环境下,--harmony参数启用ES6新特性,这些新特性只有在strict mode下才生效,因此使用"use strict"或者--use_strict,否则harmony没有被启用;

2. Extended Mode: 当启用新特性的时候,context处于extended mode下;而且这些feature仅仅只在strict mode下有效;

 

1. let与const:

  1. 块级作用域(Block scope

  2. let声明

  3. const声明

// Block scope

function f1(){

    console.log("Outside.");

}

(function(){

    if(false){
     // f1定义在if {}之内
function f1() { console.log("Inside."); } } f1(); }());

  ES5中:

  1. strict mode:     将会报错:In strict mode code, functions can only be declared at top level or immediately within another function.(函数只能声明在Glocal scope或者函数里的最外层)

  2. non-strict mode:    输出:"Inside";

  ES6中:

  1. strict mode:     输出:"Outside",(node环境下使用命令:node --harmony --use_strict 1_blockScope.js,使用node 1_blockScope.js --harmony命令,harmony没有起作用)

  2. non-strict mode:  输出:"Inside";(根据上面第一条:non-strict mode下不启用harmony)

  因为ES6中,出现了块级作用域,导致上面的代码在ES6 context的strict mode中是有意义的;

 

  let声明的变量,其作用域仅在块级作用域之内

{

    let a = 1;

    var b = 2;

}

a

b

// ES6下:ReferenceError: a is not defined

// ES5下:SyntaxError: Illegal let declaration outside extended mode

  因为let不会有变量提升,所以输出v1=5, i=10;个人感觉:之前共用函数作用域,现在增加了块级作用域不会增加内存占用吗?

function f1(){

    var list = [];

    for(var i=0; i<10; i++){

        let v1 = i;

        list.push(function(){

           console.log(v1, i);

        });

    }

    list[5]();  // output: 5 10

}

f1();

  IIFE的目的是说:定义的变量存在于函数作用域中,不在最外层Global,避免对Global的污染;基于这一目的,可以使用块级作用域来代替IIFE;

 

  定义常量,node环境下,重新赋值报错:SyntaxError: Assignment to constant variable.

const PI = 3.14;

// SyntaxError: Assignment to constant variable.

//console.log(PI=3.13);

console.log(PI);

     

 

4. Destructing析构赋值

  下面列出了析构的几个常用之处:1. 函数传参;2. 函数返回;3. 函数参数默认值;4. for..of遍历

// 1. Passing arguments

function f1({x, y}){

    console.log(arguments);

}

f1({x:"Hello", y:"Function"});





// 2. Accept function returns

var f1Ret = (function(){

    return {x: "hello", y:"function"};

})();

console.log(f1Ret);





// 3.Passing arguments with fixed arguments

function f1({x="hello", y="world"}){

    console.log(arguments);

}

f1({x:"Hi", y:"Function"});





// 4. for...of

var m1 = new Map();

m1.set("Hello", "World");

m1.set("Hi", "Map");



for(let [k, v] of m1){

    console.log(k, v);

}

5. Number扩展:

  1. Number.isFinite()

  2. Number.isNaN()

  3. Number.isInteger()

"use strict";



/**

 * Number:

 * 1. Number.isFinite(), Number.isNaN()

 * 2. Number.isInteger

 *

 */



console.log("isFinite: ", Number.isFinite(Infinity), Number.isFinite(-Infinity), Number.isFinite(0));



console.log("isNaN: ", Number.isNaN(NaN));



//console.log("parseInt: ", Number.parseInt("13.00"));



console.log(Number.isInteger(3.01));

 

 

 

6. 数组扩展:

1. Array.from(...)   抽取Array-like对象或者Interable对象
2. Array.of(...)     将零散值转换为数组
3. array.fill()      填充
4. find(fn), findIndex(fn)
"use strict";



/**

 * Array:

 * 1. Array.from(...)   抽取Array-like对象或者Interable对象

 * 2. Array.of(...)     将零散值转换为数组

 * 3. array.fill()      填充

 * 4. find(fn), findIndex(fn)

 * 5. Array.observe()   监听

 */



var m1 = new Map();

m1.set("A").set("B");



var a1 = Array.from(m1);

console.log(a1);



console.log(Array.of(10, 20, 30));



console.log([null, null].fill(10));



var a2 = [10, 20];

console.log(a2.find(function (v, i) {

    return v == 10;

}), a2.findIndex(function (v, i) {

    return v == 10;

}));

 

7. 对象扩展:

  1. Object.is

  2. Object.assign

  3. Object.getPrototype

  4. Object.setPrototypeOf

/**

 * Object.is(o1, o2)    判断对象是否相等

 * Object.assign(target, src1, src2)

 * Object.getPrototype(obj)

 * Object.setPrototypeOf(o1, o2)

 * 将对象、方法直接写入对象

 */





console.log("Object.is(+0, -0): ", Object.is(+0, -0), +0 === -0);

console.log("Object.is(NaN, NaN): ", Object.is(NaN, NaN), NaN === NaN);



var o1 = { a1: "1st" };

var o2 = { a1: "2nd" };

var o3 = { a1: "3rd" };

console.log(Object.assign(o1, o2, o3));



console.log(Object.getPrototypeOf(o1) === Object.prototype);

//console.log(Object.setPrototypeOf({}, o1).a1);



var username = "diydyq";

var eat = new Function;

var o4 = {

    username,

    eat,

    o1,

    [username]: username 

};

// { username: 'diydyq', eat: [Function], o1: { a1: '3rd' } }

console.log(o4);

 

 

8. 函数扩展:

  1. 参数默认值

  2. Rest参数(将一系列实参映射到形参数组

  3. 扩展运算符(将数组实参映射到一系列逗号分隔的形参

  4. 箭头函数(this不可更改,arguments指向的不是自身的参数)

"use strict";

var l1 = [10, 20];



/**

 * 参数默认值

 */

var f1 = function (x="default argument") {

    console.log(x);

};

f1();

f1("specified argument");





/**

 * Rest参数:

 * 1. 将一系列实参转换为数组

 */

var f2 = function (name, ...left) {

    console.log(name, left, left instanceof Array);

};

f2("s1", "s2", "s3");



/**

 * 扩展运算符(spread)

 * 1. 将数组实参转换为一系列的形参

 */

var v3 = [10, 20, 30];

var f3 = function (v1) {

    console.log(v1, arguments);

};

f3(...v3);



Math.max.apply(null, v3);

Math.max(...v3);





/**

 * 箭头函数

 * 1. this 绑定了定义时的对象,call|apply却无法更改,为什么不应该呢?

 * 2. arguments变量可以使用,但不是该函数对应的参数,而是包含它的函数的参数

 */

var f1 = v => { console.log(v); };

l1.forEach(f1);



function f2Wrap(){

    var f2 = (v) => { console.log(this == global, arguments, v == arguments[0], v && Object.prototype.valueOf.call(v)); };

    f2();

    f2(l1);

    f2.call(l1, l1);

}



f2Wrap("Test");

 

9. Set与Map操作:

  1. Set:不可重复的数组,可用于数组去重(属性:size;5个方法:set() get() has() delete() clear())

  2. Map: 存放的键名key不限于简单数据类型,支持对象作为键(属性:size;5个方法:set() get() has() delete() clear(),遍历:keys() values() entries())

  3. WeakMap: Traceur中暂不支持(TODO:待使用);

"use strict";

var l1 = [10, 20, 30, 20];

var s1 = new Set(l1);



/**

 * Set对象:

 * 1. 1个属性: size

 * 2. 4个方法:add() delete() has() clear()

 */

console.log(s1, s1.size);

console.log(s1, s1.add(100).delete(10), s1.has(100), s1.size);

console.log(s1.map_);



console.log("-------------------------------------------------");



/**

 * Map对象:

 * 1. 1个属性:size

 * 2. 多个属性:set(), get(), has(), delete(), clear()

 * 3. m.set(k, v) 不同于 m[k] = v; 后者是给这个m对象赋值;

 */

var m1 = new Map();

var o1 = { attr1: "Test" };

var o2 = [10, 20];



m1[o1] = "Value for o1";

m1.set(o1, "Value for o1 new1");

m1.set(o2, "ValueFor o2");



console.log(m1, m1[o1], m1.get(o1), m1.has(o1), m1.delete({}));

console.log(m1);

m1.clear();



m1[0] = "Value for 0";

m1.set(0, "Value, for 0 new1");

console.log(m1[0], m1.get(0), m1, m1.size);





for(let k of m1.keys()){

    console.log(k);

}

for(let v of m1.values()){

    console.log(v);

}

for(let [k, v] of m1.entries()){

    console.log(k, v);

}



/**

 * WeakMap对象:

 * TODO:traceur中找不到

 *

 */

//var wm1 = new WeakMap();

//wm1.set(o1, "Value for o1");

//wm1.set(o2, "Value for o2");

//console.log(wm1.size);

 

11 Generator函数:

  1. 每次yield或者return返回新的对象:{ value: ..., done: false|true }  
  2. return后再次调用next()返回空的value对象: { value: undefined, done: true }
  3. next()传参:
    1) 第一次next传递参数,会报错:ModuleEvaluationError: Sent value to newborn generator
    2) 所以如果第一次需要传参,可以在生成generator时添加;
    3) 后续的next参数,将作为yield表达式的返回值

"use strict";



/**

 * Generator:

 * 1. 每次yield或者return返回新的对象:{ value: ..., done: false|true }

 * 2. return后再次调用next()返回空的value对象: { value: undefined, done: true }

 * 3. next()传参:

 *    1) 第一次next传递参数,会报错:ModuleEvaluationError: Sent value to newborn generator

 *    2) 所以如果第一次需要传参,可以在生成generator时添加;

 *    3) 后续的next参数,将作为yield表达式的返回值

 */

function* generatorFrom1(arg1){

    console.log("Execute generator: ", arg1);

    var o1 = {};

    for(var i=0; i<2; i++){

        o1.idx = i;

        var yRet = yield o1;

        console.log("yield Return: ", yRet);

    }

    return o1;

}



var g1 = new generatorFrom1(), g2 = new generatorFrom1("First time execution.");

var r1, r2;



r1 = g1.next();

r2 = g1.next();

console.log(r1, r2, r1 == r2);

console.log(g1.next(), g1.next());



console.log("----------------------------------");

console.log("Execute 1: start");

r1 = g2.next();

console.log("Execute 1: end");



console.log("Execute 2: start");

r2 = g2.next("argument Test");

console.log("Execute 2: end");

console.log(r1, r2);

 

12 Promise:

  1. Promise的构造函数必须为function,否则TypeError;

  2. catch(fn)用于处理reject的信息;

  3. 如果让下一个执行resolve,则return;否则拒绝的话,使用throw new Error()

  4. Promise.all()参数是一个数组,不是零散的promise对象

"use strict";



/**

 * Promise:

 * 1. Promise的构造函数必须为function,否则TypeError;

 * 2. catch(fn)用于处理reject的信息;

 * 3. 如果让下一个执行resolve,则return;否则拒绝的话,使用throw new Error()

 * 4. Promise.all()参数是一个数组,不是零散的promise对象

 * 5. async功能未成功试用

 */



var fn1 = function(resolve, reject){

    setTimeout(function () {

        console.log("Execute promise function");

        resolve("Resoved Message");

        //reject("Rejected Message");

    }, 1000);

};



//var p1 = new Promise(fn1);

var p1 = new Promise(fn1);



p1.then(function (msg) {

    console.log("1st resolve: ", arguments);

}, function (msg) {

    console.log("1st reject: ", arguments);

    //return "1st pass to 2nd message";

    throw new Error(["1st pass rejected message"]);

}).then(function (msg) {

    console.log("2st resolve: ", arguments);

}, function (msg) {

    console.log("2st reject: ", arguments);

}).catch(function (msg) {

    console.warn("3rd reject: ", arguments);

});





var fn2 = function(resolve, reject){

    setTimeout(function () {

        console.log("Execute promise function");

        resolve("Resoved Message");

        //reject("Rejected Message");

    }, 500);

};

var p2 = new Promise(fn2);





var pAll1 = Promise.all([p1, p2]).then(function (msg) {

    console.log("1st resolve: ", arguments);

}, function (msg) {

    console.log("1st reject: ", arguments);

});



console.log("-----------------------------------");

//async function asyncFn1() {

//    console.log("Async before");

//    let ret1 = await (function () {

//        return new Promise(fn1);

//    })();

//    console.log("Async After");

//}

//asyncFn1();

 

 

 

 

参考:

1. ruanyifeng       http://es6.ruanyifeng.com/#docs/let

2. Stackoverflow    http://stackoverflow.com/questions/17253509/what-is-extended-mode

 

你可能感兴趣的:(新特性)