注意:
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