作为发布流程的一部分,大约每隔6周,我们就会创建一个新的V8分支。每个版本都是在Chrome浏览器项目创建beta milestone分支前一刻从V8的master分支创建的。今天,我们很高兴宣布我们最新的分支4.9将处于beta阶段,直到它随Chrome 49稳定版本发布。V8 4.9版本带来一些对开发者的利好,所以我们想带你预览下几周后发布的这个版本的一些亮点。
常青浏览器项目一般每6周发布一次新版本,如Chrome,Edge,Firefox。V8的发布流程跟Chrome浏览器发布流程同步。
91% 的 ECMAScript 2015(ES6) 特性支持
在V8 4.9版本中,我们发布了有史以来最多的一批JavaScript ES2015 新特性,按照Kangax 兼容表(截止2016.1.26),我们已经达到了91%的完成度。V8现在支持解构(destructuring),默认参数,代理(Proxy)对象和反射(Reflect)API。4.9版本支持非严格模式下的块级结构,如class
和let
,还支持正则表达式的sticky标记和可自定义的Object.prototype.toString
输出。
解构
变量声明、参数和赋值现在通过模式匹配支持对对象和数组的解构。例如:
let o = {a: [1, 2, 3], b: {p: 4}, c: {q: 5}};
let {a: [x, y], b: {p}, c, d} = o; // x=1, y=2, p=4, c={q: 5}
[x, y] = [y, x]; // x=2, y=1
function f({a, b}) { return [a, b] }
f({a: 4}) // [4, undefined]
数组形模式匹配可以通过剩余值模式把数组的剩余部分赋值:
let [x, y, ...r] = [1, 2, 3, 4]; // x=1, y=2, r=[3,4]
另外,模式匹配的元素可以给定默认值以处理没有对应属性的情况:
let {a: x, b: y = a} = {a: 4}; // x=4, y=4
let [x, y = 0, z = 0] = [1, 2]; // x=1, y=2, z=0
解构可以使从对象和数据获取数据的代码更紧凑。
Proxies & Reflect
经过几年的开发,V8现在有一个完全的proxies实现,完全同步到ES2015规范。通过一组开发者提供的钩子定制属性的访问,Proxies是一种强大的虚拟化对象和函数的机制。除此之外,proxies也可以用于实现属性设置的拦截、校验,简化调试和剖析,以及像membranes解锁高级抽象
欲代理一个对象,你必须创建一个定义了各种陷阱(trap)的占位句柄对象,并将它应用到代理虚拟化的目标对象:
let target = {};
let handler = {
get(receiver, name="world") {
return `Hello, ${name}!`;
}
};
let foo = new Proxy(target, handler);
foo.bar
代理对象伴随着反射模块,其为所有代理陷阱定义了适合的默认操作:
let debugMe = new Proxy({}, {
get(target, name, receiver) {
console.log(`Debug: get called for field: ${name}`);
return Reflect.get(target, name, receiver);
},
set(target, name, value, receiver) {
console.log(`Debug: set called for field: ${name}, and value: ${value}`);
return Reflect.set(target, name, value, receiver);
}
});
debugMe.name = "John Doe";
// Debug: set called for field: name, and value: John Doe
let title = `Mr. ${debugMe.name}`; // "Mr. John Doe"
// Debug: get called for field: name
更多的关于Proxies和Reflect API的使用,可以参见MDN的Proxy页面的示例章节,及在 Web Fundamentals blog查看我们即将到来Proxies相关文章。
默认参数
在ES5或更低的规范中,可选参数在函数定义中的需要样板式的代码来检查是否参数是未定义:
function sublist(list, start, end) {
if (typeof start === "undefined" || start === null) start = 0;
if (typeof end === "undefined" || end === null) end = list.length;
...
}
ES2015现在允许函数参数可以具有默认值,以提供更清晰,更简明的函数定义:
function sublist(list, start = 0, end = list.length) { ... }
sublist([1, 2, 3], 1) // sublist([1, 2, 3], 1, 3)
默认参数和解构当然也可以在一起使用:
function vector([x, y, z] = []) { ... }
sloppy模式下的Classes和词法声明
V8自版本4.1和4.2分别支持词法声明(let, const, 块级function)和类,但至今为止使用到它们需要严格模式。按照ES2015规范,V8 4.9版本中,所有这些特性现在在严格模式之外也启用。这使得可以在开发者工具控制台中制作原型容易得多,但我们还是鼓励开发者升级新代码到严格模式。
未指定模式的情况即是sloppy模式。
正则表达式
V8现在支持正则表达式的新的sticky标记。sticky标记切换字符串中的搜索是从前开始(normal)还是从lastIndexs属性开始(sticky)。在用多个不同正则表达式对任意长输入字符串进行高效解析时,这个行为是有用的。要启用sticky搜索,添加y标志到正则表达式即可:(e.g. var regex = /foo/y;)。
可定制的Object.prototype.toString输出
使用Symbol.toStringTag, 当传递用户定义的类型给Object.prototype.toString现在可以返回自定义的输出。直接或者作为字符串强制的结果:
class Custom {
get [Symbol.toStringTag]() {
return "Custom"
}
}
Object.prototype.toString.call(new Custom) // "[object Custom]"
String(new Custom) // "[object Custom]"
改进Math.random()
V8 4.9版本包含一个Math.random()的实现的改进。如上个月的公告,我们切换V8的PRNG算法到xorshift128+以提供更高质量的伪随机性。
V8 API
请检查我们的API修改汇总。每个主要版本发布后,该文件经常已经更新了几个礼拜了。
积极更新的开发者们可以使用git checkout -b 4.9 -t branch-heads/4.9
来体验V8 4.9版本的新特性。另外你可以订阅Chrome’s Beta频道并自己尝试新功能。