Javascript spread运算符是否影响性能?

Javascript spread运算符是否影响性能?,javascript,arrays,node.js,Javascript,Arrays,Node.js,我正在考虑以下两种构建对象阵列的方法: 方法1(列出所有属性,即使在对象之间重复): 方法2(避免与排列操作员重复): 方法2更简洁,添加一个对所有数组元素都通用的新属性将更容易(并且不容易出错) 但是,对于大型commonParams对象,与方法1相比,方法2(使用扩展运算符)是否会影响性能 spread运算符是否会针对employees数组中的每个对象循环遍历commonParams对象的每个属性?是,将引用对象的变量扩展到另一个对象需要解释器查找该变量引用的内容,然后查找对象的所有可枚举自

我正在考虑以下两种构建对象阵列的方法:

方法1(列出所有属性,即使在对象之间重复):

方法2(避免与排列操作员重复):

方法2更简洁,添加一个对所有数组元素都通用的新属性将更容易(并且不容易出错)

但是,对于大型
commonParams
对象,与方法1相比,方法2(使用扩展运算符)是否会影响性能


spread运算符是否会针对
employees
数组中的每个对象循环遍历
commonParams
对象的每个属性?

是,将引用对象的变量扩展到另一个对象需要解释器查找该变量引用的内容,然后查找对象的所有可枚举自身属性(以及相关值),这些属性被扩展以插入到新对象中。这确实需要一点处理能力

但是,在现代计算机和现代JS引擎上,所需的处理能力几乎为零;当每秒可以处理数百万条指令时,这又有什么关系呢?一些键值对没有什么好担心的

除非您已经确定您正在传播一个包含大量键值对的对象,并且它实际上造成了性能瓶颈,否则最好避免过早的优化,并以编写干净、可读的代码为目标(这可能会经常使用扩展语法调用)。对于大型
employees
数组,第二种方法比第一种更具可读性

(不过,您也可以考虑使用<代码> .map < /COD>,以保持代码甚至干涸ER:)/p>


运行第二种方法的时间将更长(即使在现代计算机上很少),因为解释器必须迭代commonParams的键并将它们复制到每个对象

编写了一个基准测试,以发现小对象的差异几乎为零

函数runFirstApproach(){
施工人员1=[
{
公司:“ABC”,
国家:'在',
邮编:123,
雇员编号:123,
员工名称:“p”
},
{
公司:“ABC”,
国家:'在',
邮编:123,
雇员ID:456,
员工名称:“q”
},
{
公司:“ABC”,
国家:'在',
邮编:123,
雇员ID:789,
雇员名称:“r”
}
];
}
函数runSecondApproach(){
常量commonParams={
公司:“ABC”,
国家:'在',
邮政编码:123
};
施工人员2=[
{
…公共参数,
雇员编号:123,
员工名称:“p”
},
{
…公共参数,
雇员ID:456,
员工名称:“q”
},
{
…公共参数,
雇员ID:789,
雇员名称:“r”
}
]
}
函数runBenchmarkWithFirstApproach(){
log(“运行第一次进近的平均时间->”,getAvgRunTime(runFirstApproach,100000))
}
函数runbenchmarkwithsecondaproach(){
log(“运行第二次进近的平均时间->”,getAvgRunTime(运行第二次进近,100000))
}
函数getAvgRunTime(func,rep){
设totalTime=0;
让tempRep=rep;
而(tempRep--){
const startTime=Date.now();
func();
const endTime=Date.now();
const timetake=结束时间开始时间;
总时间+=所用时间;
}
返回totalTime/rep;
}
运行BenchmarkWithFirstApproach();

运行BenchmarkWithSecondApproach()传播的成本是巨大的。我们这里说的是两个数量级

const { x, y } = z

z = { x, y: y + 1 } // faster
z = { ...z, y: y + 1 } // slower
虽然它们都完成了相似的任务,但它们的性能特征却大不相同。但这将取决于JavaScript是否以及如何传输

例如,如果您以ES2015为目标,巴别塔实际上会发出类似于更快的变体的东西,但如果您以ES2017为目标,您将得到较慢的变体,就像现在一样。如果您使用Google Closure编译器以ECMASCRIPT_2018为目标,则会得到较慢的变体。使用TypeScript编译器,您最终得到的对象数量是原来的两倍,因为它执行嵌套的
Object.assign
调用

虽然传播速度较慢,但每秒仍有大量的行动。只是如果你以一种无聊的方式来做,你每秒会得到更多的行动

我放了一个jsperf示例来说明这一点


如果有一个扩展的热代码路径,请考虑直接构造。否则,就不用麻烦了。

如果有人在这个问题上结结巴巴地想知道数组排列操作而不是对象:

我采用不同的方法来完成:

const clone = [...original]
var-original=[];
var克隆=[];
对于(变量i=0;i<10000000;i++){
原件。推送(1);
}
var循环=0;
var-spreadTime=[];
var-mapTime=[];
var forTime=[];
var还原时间=[];
var切片时间=[];
var arrayFromTime=[];
而(周期<10){
var d=Date.now();
克隆=[];
克隆=[…原始];
spreadTime.push(Date.now()-d);
d=日期。现在();
克隆=[];
clone=original.map((条目)=>entry);
mapTime.push(Date.now()-d);
d=日期。现在();
克隆=[];
对于(变量i=0;i{
下一步,推(e);
下一步返回;
}, []);
reduceTime.push(Date.now()-d);
d=日期。现在();
克隆=[];
clone=original.slice();
sliceTime.push(Date.now()-d);
d=日期。现在();
克隆=[];
克隆=数组。从(原始);
arrayFromTime.push(Date.now()-d);
循环++;
document.getElementById(“cycle”).innerHTML=cycle;
document.getElementById(“spreadTime”).innerHTML=spreadTime.reduce((a,b)=>a+b,0)/spreadTime.length;
document.getElementById(“mapTime”).innerHTML=mapTime.reduce((a,b)=>a+b,0)/mapTime.length;
document.getElementById(“forTime”).innerHTML=forTime.reduce
const employeesInitial = [
  {
    employeeId: 123,
    employeeName: 'p'
  },
  {
    employeeId: 456,
    employeeName: 'q'
  },
  {
    employeeId: 789,
    employeeName: 'r'
  }
];
const employees = employeesInitial.map((obj) => ({ ...obj, ...commonParams }));
const { x, y } = z

z = { x, y: y + 1 } // faster
z = { ...z, y: y + 1 } // slower
const clone = [...original]