gpt4 book ai didi

javascript - 为什么 Array.prototype.find() polyfill 比 ES6 实现慢?

转载 作者:行者123 更新时间:2023-11-30 11:06:08 25 4
gpt4 key购买 nike

我的印象是大多数 ES6 特性只是语法糖。但是,当我比较 MDN 上的 find polyfill 时使用常规的 ES6 实现,它似乎快了一半。究竟是什么解释了这种性能差异,难道在引擎盖下不都是一样的吗?

请引用下面的代码片段以获取基准:

// Find polyfill
function find(obj, predicate) {
// 1. Let O be ? ToObject(this value).
if (this == null) {
throw new TypeError('"this" is null or not defined');
}

var o = Object(obj);

// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;

// 3. If IsCallable(predicate) is false, throw a TypeError exception.
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}

// 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
var thisArg = arguments[1];

// 5. Let k be 0.
var k = 0;

// 6. Repeat, while k < len
while (k < len) {
// a. Let Pk be ! ToString(k).
// b. Let kValue be ? Get(O, Pk).
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
// d. If testResult is true, return kValue.
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return kValue;
}
// e. Increase k by 1.
k++;
}

// 7. Return undefined.
return undefined;
}
const testArray = ["Hello", "Hi", "Good Morning", "Good Afternoon", "Good Evening", "Good Night"];

// Polyfill benchmark
console.time('findPolyfill');
for (var i = 0; i < 10000; i++) {
find(testArray, (item) => item === "Hello")
}
console.timeEnd('findPolyfill');

// ES6 benchmark
console.time('find ES6');
for (var i = 0; i < 10000; i++) {
testArray.find((item) => item === "Hello");
}
console.timeEnd('find ES6');

最佳答案

native 版本可以利用内部优化和快捷方式,只要它们不能从外部观察到。如果不是编译的机器代码,它也可能被预先优化并至少存储为字节码。 (取决于 JavaScript 引擎。)

相比之下,polyfill 是对规范所说的内容的非常迂腐的呈现,除非你在一个紧密的循环中运行它超过 5-10k 次左右,否则不太可能被选择用于积极优化引擎。

有趣的是,您的循环设置为运行 10k 次,因此很可能就在引擎对其进行优化之前停止。或者引擎可能会在中途优化它——进一步延迟结果。例如,对我来说,下面的 polyfill 第一次运行时间约为 6 毫秒,但第二次和第三次运行时间约为 1.1 毫秒(Chrome v73 中的 V8 v7.3)。所以很明显它在第一次运行时得到了优化(反常地,这可能会减慢运行速度,但显然会加快后续运行速度)。

// Find polyfill
function find(obj, predicate) {
// 1. Let O be ? ToObject(this value).
if (this == null) {
throw new TypeError('"this" is null or not defined');
}

var o = Object(obj);

// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;

// 3. If IsCallable(predicate) is false, throw a TypeError exception.
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}

// 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
var thisArg = arguments[1];

// 5. Let k be 0.
var k = 0;

// 6. Repeat, while k < len
while (k < len) {
// a. Let Pk be ! ToString(k).
// b. Let kValue be ? Get(O, Pk).
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
// d. If testResult is true, return kValue.
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return kValue;
}
// e. Increase k by 1.
k++;
}

// 7. Return undefined.
return undefined;
}
const testArray = ["Hello", "Hi", "Good Morning", "Good Afternoon", "Good Evening", "Good Night"];

function testPolyfill() {
// Polyfill benchmark
console.time('findPolyfill');
for (var i = 0; i < 10000; i++) {
find(testArray, (item) => item === "Hello")
}
console.timeEnd('findPolyfill');
}

function testNative() {
// ES6 benchmark
console.time('find ES6');
for (var i = 0; i < 10000; i++) {
testArray.find((item) => item === "Hello");
}
console.timeEnd('find ES6');
}

testPolyfill();
testNative();
testPolyfill();
testNative();
testPolyfill();
testNative();

关于javascript - 为什么 Array.prototype.find() polyfill 比 ES6 实现慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55534013/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com