我自己也在想这个问题。于是我决定进行测试。以下是我的测试代码:
var a = "Here's a string value";
var b = 5;
var c = false;
var object = {
a, b, c
}
var array = [
a, b, c
];
var passObject = (obj) => {
return obj.a.length + obj.b * obj.c ? 2 : 1;
}
var passRawValues = (val_a, val_b, val_c) => {
return val_a.length + val_b * val_c ? 2 : 1;
}
var passArray = (arr) => {
return arr[0].length + arr[1] * arr[2] ? 2 : 1;
}
var x = 0;
然后我像这样调用了三个函数:
x << 1;
x ^= passObject(object);
x << 1;
x ^= passRawValues(a, b, c);
x << 1;
x ^= passArray(array);
它进行位移和异或的原因是,如果没有这些操作,一些JS运行时会完全优化掉函数调用。通过存储函数结果,我强制运行时实际执行函数调用。
结果
在Webkit和Chromium中,传递对象和传递数组的速度大致相同,传递原始值稍微慢一些。Firefox显示了大致相同的性能比例,但我不确定是否信任结果,因为它比Chromium快了十倍。
这里是我的MeasureThat上的测试用例链接。如果链接无法使用:它与上面的代码相同。
这是运行结果的屏幕截图(在M1 Macbook Air上的Chromium中):
在Chromium中,传递对象的操作速度约为500万次/秒,而传递三个基本值的速度约为370万次/秒。
解释
那么为什么会这样呢?嗯,JavaScript 严格使用传值语义。但是当你将一个对象传递给函数时,你传递的值实际上并不是对象本身,而是指向对象的指针。因此,存储指针的变量被复制了,但它所指向的内容并没有被复制。这也是为什么你可以有一个函数,它接受一个对象并改变它的属性,这个改变也会发生在函数外部,但如果你重新分配对象,外部作用域仍然引用旧对象。
因此,传递的对象的大小对性能来说基本无关紧要。如果上面的 var object = {...}
被更改以包含大量其他数据,则将其传递给函数时每秒执行的操作数量仍然完全相同,因为唯一变化的是存储对象的内存块中的数据量。传递给函数的值并不会因为对象变得更大而变得更大。