gpt4 book ai didi

javascript - TypeScript 转译 - for 循环与数组切片

转载 作者:搜寻专家 更新时间:2023-10-30 21:09:47 26 4
gpt4 key购买 nike

在 ES6 中,我们可以使用 rest 参数,有效地创建一个参数数组。 TypeScript 使用 for 循环将其转换为 ES5。我想知道是否存在使用 for 循环方法比使用 Array.prototype.slice 更好的选择?也许有 slice 选项没有涵盖的边缘情况?

// Written in TypeScript
/*
const namesJoinTS = function (firstName, ...args) {
return [firstName, ...args].join(' ');
}

const res = namesJoinTS('Dave', 'B', 'Smith');
console.log(res)
*/

// TypeScript above transpiles to this:
var namesJoinTS = function (firstName) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
return [firstName].concat(args).join(' ');
};
var res = namesJoinTS('Dave', 'B', 'Smith');
console.log(res); //Dave B Smith

// Vanilla JS
var namesJoinJS = function (firstName) {
var args = [].slice.call(arguments, 1);
return [firstName].concat(args).join(' ');
};
var res = namesJoinJS('Dave', 'B', 'Smith');
console.log(res); // //Dave B Smith

最佳答案

这种奇怪的转译是 V8 旧版本(并且可能仍然存在)的偏向优化的副作用。他们极大地优化了某些特定模式但并不关心整体性能,因此一些奇怪的模式(如 for 循环将 arguments 复制到数组 *)确实跑得更快。因此,库和转译器的维护者开始寻找据此优化代码的方法,因为他们的代码在数百万台设备上运行并且每一毫秒都很重要。现在,随着 V8 中的优化变得更加成熟并且专注于平均性能,这些技巧中的大多数都不再起作用了。他们从代码库中重构出来只是时间问题。

此外,JavaScript 正在朝着一种可以更轻松地优化的语言发展,旧功能(如 arguments)被更严格的新功能(rest 属性)所取代,因此性能更高。使用它们可以通过漂亮的代码实现良好的性能,arguments 是过去的错误。

I was wondering is there any scenarios where using the for loop approach is a better option than using Array.prototype.slice?

嗯,它在旧的 V8 版本上更快,是否仍然需要测试。如果您为项目编写代码,我总是会选择更优雅的解决方案,在 99% 的情况下,理论上您可能损失的毫秒数并不重要。

Maybe there are edge cases that the slice option does not cover?

没有(据我所知)


*您可能会问“为什么它更快?”,那是因为:

arguments 本身很难优化,因为

1) 可以重新赋值 (arguments = 3)

2) 它必须是“实时的”,改变参数将反射(reflect)到 arguments

因此,只有当您直接访问它时,它才能被优化,因为编译器可能会用变量引用替换类似数组的访问器:

 function slow(a) {
console.log(arguments[0]);
}

// can be turned into this by the engine:
function fast(a) {
console.log(a);
}

如果您内联循环并在参数数量发生变化时回退到另一个(可能更慢)版本,这也适用于循环:

 function slow() {
for(let i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}

slow(1, 2, 3);
slow(4, 5, 6);
slow("what?");

// can be optimized to:
function fast(a, b, c) {
console.log(a);
console.log(b);
console.log(c);
}

function fast2(a) {
console.log(a);
}

fast(1,2,3);
fast(4, 5, 6);
fast2("what?");

现在,如果您调用另一个函数并传入参数,事情就会变得非常复杂:

 var leaking;

function cantBeOptimized(a) {
leak(arguments); // uurgh
a = 1; // this has to be reflected to "leaking" ....
}

function leak(stuff) { leaking = stuff; }

cantBeOptimized(0);
console.log(leaking[0]); // has to be 1

这无法真正优化,这是一个性能噩梦。因此,调用一个函数并传递 arguments 在性能方面是个坏主意。

关于javascript - TypeScript 转译 - for 循环与数组切片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54723231/

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