夜下客

繁体版 简体版
夜下客 > JS修炼法则 > 第24章 V8高效扩展元素

第24章 V8高效扩展元素

一.前言

邓黄海在2018年V8团队实习时,他致力于提升了[...array]、[...string]、[...set]、[...map.keys()]和[...map.values()]的性能。他甚至使得Array.from(iterable)更快了。

关于本文分享的他的魔改细节,你可以大胆食用!因为这些优化从 V87.2版本就已经带上了。你也不需要过度担心你的代码,特别是使用...的代码。

额外插一句,邓黄海是越南人,不是中国人嗷。他博士毕业于 MPI-SWS。在当时他使用 V8 的内部语言CodeStubAssembler (CSA) 优化 JavaScript 代码。CSA 是一种基于 C++ 的类似汇编的 goto 语言,可为 Chrome 支持每种架构并生成汇编代码。

二.扩展元素

...操作符英文名称是Spreadsyntax,译为扩展语法(展开语法)。它只能对iterableObj进行操作。iterableObj会提供一个迭代器,即可通过[Symbol.iterator]()进行访问。

所以,扩展元素的定义是 使用了...的元素,即形如...iterableObj。

它在 ES2015 中作为一种从iterable objects中创建数组的方式而被引入。例如:

const a = [2, 3];

const b = [5, 6, 7];

const result = [1, ...a, 4, ...b];

// → [1, 2, 3, 4, 5, 6, 7]

const str = '阿吉的公众号';

const result = [...str];

// → ['阿', '吉', '的', '公', '众', '号']

const s = new Set();

s.add('V8');

s.add('TurboFan');

const result = [...s];

// → ['V8', 'TurboFan']

举个简单例子,浅克隆一个数组arr,在ES6中我们常用[...arr]。

很不幸,这种惯用方式的性能远远落后于它的 ES5 对应物,即用ES5自定义一个浅克隆数组方法。

但当前你可以放心,邓黄海实习时致力于解决这个问题,当前已经解决。

三.为何曾经扩展元素很慢

有很多方法可以对数组进行浅克隆,比如arr.slice()、arr.concat()、[...arr],甚至可以用for循环自定义一个clone方法。如下:

function clone(arr) {

// Pre-allocate the correct number of elements, to avoid

// having to grow the array.

const result = new Array(arr.length);

for (let i = 0; i < arr.length; i++) {

result[i] = arr[i];

return result;

理想情况下,上述提及的几种方式,性能应该大致相近。

但很不幸,在v7.2之前,[...arr]会比自定义的clone都慢。因为本质上V8会把[...arr]转换成如下:

function(arr) {

const result = [];

const iterator = arr[Symbol.iterator]();

const next = iterator.next;

for ( ; ; ) {

const iteratorResult = next.call(iterator);

if (ite

『加入书签,方便阅读』