[ES6 ] ing
#
Spread operator(展开运算符) ...
允许一个表达式在某处展开,在多个参数(用于函数调用)或者多个元素(用于数组字面量)或者多个变量(用于解构赋值)的地方就会这样。
#代替apply方法
function f(x, y, z) {
console.log(arguments);//[0, 1, 2]
}
var args = [0, 1, 2];
f.apply(null, args);
function f(x, y, z) {
console.warn(arguments);//[0, 1, 2]
}
var args = [0, 1, 2];
f(...args);
#
function f(v, w, x, y, z) {
console.log(arguments); //[-1, 0, 1, 2, 3]
}
var args = [0, 1];
f(-1, ...args, 2, ...[3]);
#配合new运算符
在ES5中,无法同时使用new运算符和apply方法(apply方法调用[[Call]]而不是[[Construct]]).
在ES6中,可以使用展开运算符,和普通的函数调用一样.
var dataFields = readDateFields(database);
var d = new Date(...dateFields);
#合并数组。与 concat的区别
//改变原数组 var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; // 将arr2中的所有元素添加到arr1中 Array.prototype.push.apply(arr1, arr2); console.log(arr1); //[0, 1, 2, 3, 4, 5] //改变原数组 var arr3 = [0, 1, 2]; var arr4 = [3, 4, 5]; arr3.push(...arr4); console.log(arr3); //[0, 1, 2, 3, 4, 5] //不改变原数组 var arr5 = [0, 1, 2]; var arr6 = [3, 4, 5]; var c = arr5.concat(arr6); console.log(c); //[0, 1, 2, 3, 4, 5]
#将类数组对象转换成数组
var nodeList = document.querySelectorAll('div');
//[].slice.call(nodeList);
var array = [...nodeList];
Arrow functions(箭头函数) =>
就是个简写形式的函数表达式,并且它拥有词法作用域的this值(即不会新产生自己作用域下的this, arguments, super 和 new.target 等对象)。此外,箭头函数总是匿名的。
基础语法
(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
// equivalent to: => { return expression; }
// 如果只有一个参数,圆括号是可选的:
(singleParam) => { statements }
singleParam => { statements }
// 无参数的函数需要使用圆括号:
() => { statements }
高级语法
// 返回对象字面量时应当用圆括号将其包起来:
params => ({foo: bar})
// 支持 Rest parameters 和 default parameters:
(param1, param2, ...rest) => { statements }
(param1 = defaultValue1, param2, …, paramN = defaultValueN) => { statements }
// Destructuring within the parameter list is also supported
var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f(); // 6
#
var a = [
"Hydrogen",
"Helium",
"Lithium",
"Beryllium"
];
var a2 = a.map(function(s){ return s.length });
var a3 = a.map( s => s.length );
#箭头函数则会捕获其所在上下文的 this
值,作为自己的 this
值,因此下面的代码将如期运行。
function Person(){
this.age = 0;
setInterval(() => {
this.age++; // |this| 正确地指向了 person 对象
}, 1000);
}
var p = new Person();
#与 strict mode 的关系
考虑到 this 是词法层面上的,严格模式中与 this 相关的规则都将被忽略。
严格模式的其他规则依然不变.
var f = () => {'use strict'; return this};
f() === window; // 或全局对象
#使用 call 或 apply 调用
由于 this 已经在词法层面完成了bound,通过 call() 或 apply() 方法调用一个函数时,只是传入了参数而已,对 this 并没有什么影响:
var adder = {
base: 1,
add: function(a) {
var f = v => v + this.base;
return f(a);
},
addThruCall: function(a) {
var f = v => v + this.base;
var b = {
base: 2
};
return f.call(b, a);
}
};
console.log(adder.add(1)); // 输出 2
console.log(adder.addThruCall(1)); // 仍然输出 2(而不是3)
function addCall(a) {
var f = function(v) {
return v + this.base;
}
var b = {
base: 2
};
return f.call(b, a);
}
console.info(addCall(1)); //3
#使用 yield 关键字
yield 关键字通常不能在箭头函数中使用(except when permitted within functions further nested within it)。因此,箭头函数不能用作Generator函数。
#more
//返回对象字面量
var func = () => ({ foo: 1 });
// 一个空箭头函数,返回 undefined
let empty = () => {};
(() => "foobar")() // 返回 "foobar"
var simple = a => a > 15 ? 15 : a;
simple(16); // 15
simple(10); // 10
let max = (a, b) => a > b ? a : b;
// Easy array filtering, mapping, ...
var arr = [5, 6, 13, 0, 1, 18, 23];
var sum = arr.reduce((a, b) => a + b); // 66
var even = arr.filter(v => v % 2 == 0); // [6, 0, 18]
var double = arr.map(v => v * 2); // [10, 12, 26, 0, 2, 36, 46]
for...of
for (variable of object)
statement
语句在可迭代对象(包括 Array, Map, Set, 参数 对象等等)上创建一个迭代循环,对每个不同属性的属性值,调用一个自定义的有执行语句的迭代挂钩.
#与for...in的区别
let arr = [ 3, 5, 7 ];
arr.foo = "hello";
//key
for (let i in arr) {
console.log(i); // logs "0", "1", "2", "foo"
}
//value
for (let i of arr) {
console.log(i); // logs "3", "5", "7"
}
#更简洁的遍历DOM元素集合
let articleParagraphs = document.querySelectorAll("article > p");
for (let paragraph of articleParagraphs) {
paragraph.classList.add("read");
}
#遍历生成器
function* fibonacci() { // 一个生成器函数
let [prev, curr] = [0, 1];
for (;;) {
[prev, curr] = [curr, prev + curr];
yield curr;
}
}
for (let n of fibonacci()) {
// 当n大于1000时跳出循环
if (n > 1000)
break;
print(n);
}
Default parameters(默认参数值)
function [name]([param1[ = defaultValue1 ][, ..., paramN[ = defaultValueN ]]]) {
statements
}
如果一个形参没有被传入对应的实参或者传入了undefined,则该形参会被赋一个默认值.
#
function setBackgroundColor(element, color = 'rosybrown') { element.style.backgroundColor = color; } setBackgroundColor(someDiv); // color的值为'rosybrown' setBackgroundColor(someDiv, undefined); // color的值为'rosybrown' setBackgroundColor(someDiv, 'blue'); // color的值为'blue'
Proxy
var p = new Proxy(target, handler);
Proxy 对象用来为基础操作(例如:属性查找、赋值、枚举、方法调用等)定义用户自定义行为。
#当对象中不存在属性名时,返回默认数为37
var handler = { get: function(target, name){ return name in target? target[name] : 37; } }; var p = new Proxy({}, handler); p.a = 1; p.b = undefined; console.log(p.a, p.b); // 1, undefined console.log('c' in p, p.c); // false, 37
#无操作转发代理
使用了一个 JavaScript 对象,代理将所有应用到它的操作转发到了这个对象上。
var target = {}; var p = new Proxy(target, {}); p.a = 37; // 被转发到代理的操作 console.log(target.a); // 37. 操作已经被正确地转发
Reflect
Reflect 对象提供了若干个能对任意对象进行某种特定的可拦截操作(interceptable operation)的方法。
和其他大多数全局对象不同的是,Reflect 并不是一个构造函数,不需要使用 new 运算符来构造它的实例。
TypedArray
new TypedArray(length);
new TypedArray(typedArray);
new TypedArray(object);
new TypedArray(buffer [, byteOffset [, length]]);
where TypedArray() is one of:
Int8Array();
Uint8Array();
Uint8ClampedArray();
Int16Array();
Uint16Array();
Int32Array();
Uint32Array();
Float32Array();
Float64Array();
#
// Setting and getting using standard array syntax var int16 = new Int16Array(2); int16[0] = 42; console.log(int16[0]); // 42 // Indexed properties on prototypes are not consulted (Fx 25) Int8Array.prototype[20] = "foo"; (new Int8Array(32))[20]; // 0 // even when out of bound Int8Array.prototype[20] = "foo"; (new Int8Array(8))[20]; // undefined // or with negative integers Int8Array.prototype[-1] = "foo"; (new Int8Array(8))[-1]; // undefined // Named properties are allowed, though (Fx 30) Int8Array.prototype.foo = "bar"; (new Int8Array(32)).foo; // "bar"