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

 

posted on 2014-12-28 17:46  diydyq  阅读(2014)  评论(0编辑  收藏  举报

导航