原文地址 ECMAScript 6 — New Features: Overview & Comparison
本文介绍 ECMAScript 6中的新特性并通过具体代码演示与ECMAScript 5的差别。译者额外增加了一些例子和说明 .
ECMAScript 6 是2015年推出的第6版本的ECMAScript标准(即Javascript标准),同时也被成为ECMAScript 2015.
ECMAScript 6 中定了了许多新的Javascript特性,包括新的类和模块,类似python的generators和generators表达式, 箭头函数, 二进制数据, 类型数组, 集合类型(maps, set & 弱maps), promises, reflection, proxy等。它也被称作 ES6 Harmony. (和谐ES6)
本文是该系列文章的第四篇
新内建方法
对象属性的赋值
新的assign函数可以枚举属性并指定一个或者多个对象映射到目标对象中
ECMAScript 6的实现
var dest = { quux: 0 }
var src1 = { foo: 1, bar: 2 }
var src2 = { foo: 3, baz: 4 }
Object.assign(dest, src1, src2) // assign src1, src2的属性到 dest对象中
dest.quux === 0
dest.foo === 3
dest.bar === 2
dest.baz === 4
对比ECMAScript 5的实现
var dest = { quux: 0 };
var src1 = { foo: 1, bar: 2 };
var src2 = { foo: 3, baz: 4 };
Object.keys(src1).forEach(function(k) { // 需要遍历key并取值赋值
dest[k] = src1[k];
});
Object.keys(src2).forEach(function(k) {
dest[k] = src2[k];
});
dest.quux === 0;
dest.foo === 3;
dest.bar === 2;
dest.baz === 4;
数组元素的寻找
新的方法用来寻找数组中的元素
ECMAScript 6的实现
// 这个find/findIndex函数只寻找返回满足条件的第一个元素
[ 1, 3, 4, 2 ].find(x => x > 3) // 4
[ 1, 3, 4, 2 ].findIndex(x => x > 3) // 2
对比ECMAScript 5的实现
[ 1, 3, 4, 2 ].filter(function (x) { return x > 3; })[0]; // 4
// ES5中无findIndex
字符串重复
新的repeat方法来重复字符串
ECMAScript 6的实现
" ".repeat(4 * depth)
"foo".repeat(3)
对比ECMAScript 5的实现
Array((4 * depth) + 1).join(" ");
Array(3 + 1).join("foo");
字符串查找
新的statsWith endsWith和includes 方法用来查找字符串
ECMAScript 6的实现
"hello".startsWith("ello", 1) // true
"hello".endsWith("hell", 4) // true
"hello".includes("ell") // true
"hello".includes("ell", 1) // true
"hello".includes("ell", 2) // false
对比ECMAScript 5的实现
"hello".indexOf("ello") === 1; // true
"hello".indexOf("hell") === (4 - "hell".length); // true
"hello".indexOf("ell") !== -1; // true
"hello".indexOf("ell", 1) !== -1; // true
"hello".indexOf("ell", 2) !== -1; // false
数值类型检查
检查是否为NaN和无穷数值
ECMAScript 6的实现
Number.isNaN(42) === false
Number.isNaN(NaN) === true
Number.isFinite(Infinity) === false
Number.isFinite(-Infinity) === false
Number.isFinite(NaN) === false
Number.isFinite(123) === true
对比ECMAScript 5的实现
var isNaN = function (n) {
return n !== n;
};
var isFinite = function (v) {
return (typeof v === "number" && !isNaN(v) && v !== Infinity && v !== -Infinity);
};
isNaN(42) === false;
isNaN(NaN) === true;
isFinite(Infinity) === false;
isFinite(-Infinity) === false;
isFinite(NaN) === false;
isFinite(123) === true;
数值的安全检查
检查一个数字的值是否在安全的范围内, 例如能够正确的以javascript展示(其实说有的数值,包括integer数值,都是浮点数值)
ECMAScript 6的实现
Number.isSafeInteger(42) === true
Number.isSafeInteger(9007199254740992) === false
对比ECMAScript 5的实现
function isSafeInteger (n) {
return (
typeof n === 'number'
&& Math.round(n) === n
&& -(Math.pow(2, 53) - 1) <= n
&& n <= (Math.pow(2, 53) - 1)
);
}
isSafeInteger(42) === true;
isSafeInteger(9007199254740992) === false;
数值的比较
提供了标准的 Epsilon (临界值),用来作为浮点数直接的比较依据。
ECMAScript 6的实现
console.log(0.1 + 0.2 === 0.3) // false
console.log(Math.abs((0.1 + 0.2) - 0.3) < Number.EPSILON) // true
对比ECMAScript 5的实现
console.log(0.1 + 0.2 === 0.3); // false
console.log(Math.abs((0.1 + 0.2) - 0.3) < 2.220446049250313e-16); // true
数值截断
讲浮点(float)数截断为整型(integer)数值, 这里的截断是完全去掉小数点后的值
ECMAScript 6的实现
console.log(Math.trunc(42.7)) // 42
console.log(Math.trunc( 0.1)) // 0
console.log(Math.trunc(-0.1)) // -0
对比ECMAScript 5的实现
function mathTrunc (x) {
return (x < 0 ? Math.ceil(x) : Math.floor(x));
}
console.log(mathTrunc(42.7)) // 42
console.log(mathTrunc( 0.1)) // 0
console.log(mathTrunc(-0.1)) // -0
数值符号选定
确定一个数值的符号, 包括带符号0和非数值.
ECMAScript 6的实现
console.log(Math.sign(7)) // 1
console.log(Math.sign(0)) // 0
console.log(Math.sign(-0)) // -0
console.log(Math.sign(-7)) // -1
console.log(Math.sign(NaN)) // NaN
对比ECMAScript 5的实现
function mathSign (x) {
return ((x === 0 || isNaN(x)) ? x : (x > 0 ? 1 : -1));
}
console.log(mathSign(7)) // 1
console.log(mathSign(0)) // 0
console.log(mathSign(-0)) // -0
console.log(mathSign(-7)) // -1
console.log(mathSign(NaN)) // NaN
Promise
Promise的使用
首先是关于如果表述一个异步在未来可以获取到的值的表达式. 更多Promise的信息.
ECMAScript 6的实现
function msgAfterTimeout (msg, who, timeout) {
return new Promise((resolve, reject) => { // 返回的promise, 会异步,在未来的某个时间调用resolve来完成
setTimeout(() => resolve(`${msg} Hello ${who}!`), timeout)
})
}
msgAfterTimeout("", "Foo", 100).then((msg) => // 对于完成的promise需要通过then来继续实现
msgAfterTimeout(msg, "Bar", 200)
).then((msg) => {
console.log(`done after 300ms:${msg}`)
})
对比ECMAScript 5的实现
function msgAfterTimeout (msg, who, timeout, onDone) {
setTimeout(function () {
onDone(msg + " Hello " + who + "!");
}, timeout);
}
msgAfterTimeout("", "Foo", 100, function (msg) {
msgAfterTimeout(msg, "Bar", 200, function (msg) {
console.log("done after 300ms:" + msg);
});
});
Promise的联合
同时也可以把多个promise联合到一个新的promise, 等待他们的完成,无需关心他们的中间执行顺序。
ECMAScript 6的实现
function fetchAsync (url, timeout, onData, onError) {
…
}
let fetchPromised = (url, timeout) => {
return new Promise((resolve, reject) => {
fetchAsync(url, timeout, resolve, reject)
})
}
Promise.all([
fetchPromised("http://backend/foo.txt", 500),
fetchPromised("http://backend/bar.txt", 500),
fetchPromised("http://backend/baz.txt", 500)
]).then((data) => {
let [ foo, bar, baz ] = data // 返回的数值是按照promise排列的顺序执行
console.log(`success: foo=${foo} bar=${bar} baz=${baz}`)
}, (err) => {
console.log(`error: ${err}`)
})
对比ECMAScript 5的实现
function fetchAsync (url, timeout, onData, onError) {
…
}
function fetchAll (request, onData, onError) {
var result = [], results = 0;
for (var i = 0; i < request.length; i++) {
result[i] = null;
(function (i) {
fetchAsync(request[i].url, request[i].timeout, function (data) {
result[i] = data;
if (++results === request.length)
onData(result);
}, onError);
})(i);
}
}
fetchAll([
{ url: "http://backend/foo.txt", timeout: 500 },
{ url: "http://backend/bar.txt", timeout: 500 },
{ url: "http://backend/baz.txt", timeout: 500 }
], function (data) {
var foo = data[0], bar = data[1], baz = data[2];
console.log("success: foo=" + foo + " bar=" + bar + " baz=" + baz);
}, function (err) {
console.log("error: " + err);
});
元程序
Proxying
Proxy能够嵌入运行时对象的元操作.
ECMAScript 6的实现
let target = {
foo: "Welcome, foo"
}
let proxy = new Proxy(target, { // 定义了一个针对对象的proxy, 重定义了get元操作.
get (receiver, name) {
return name in receiver ? receiver[name] : `Hello, ${name}`
}
})
proxy.foo === "Welcome, foo"
proxy.world === "Hello, world"
对比ECMAScript 5的实现
// ES5中无
Reflection
针对Object的一系列操作,和之前的Object.方法不同的是,reflection的返回值是有意义的。
Reflection提供了一系列的操作方法,这里的例子中只有一个,更详细的请看这里 - 译者会跟进翻译这篇文章。
ECMAScript 6的实现
let obj = { a: 1 }
Object.defineProperty(obj, "b", { value: 2 })
obj[Symbol("c")] = 3
Reflect.ownKeys(obj) // [ "a", "b", Symbol(c) ] // 这里只介绍了ownKeys这个方法
对比ECMAScript 5的实现
var obj = { a: 1 };
Object.defineProperty(obj, "b", { value: 2 });
// no equivalent in ES5
Object.getOwnPropertyNames(obj); // [ "a", "b" ]
网友评论