如果未设置,请设置密钥 - 哪种方式最有效

Setting a key if it's not set - which way is the most efficient?

本文关键字:设置 方式最 有效 密钥 如果      更新时间:2023-09-26

检查是否在对象上设置了键的最有效方法是什么,如果没有,则将其设置为给定值?请记住,这仅适用于高性能案例

假设someCostlyOperation()需要大量的 CPU 时间来计算,并且从不返回错误值

方法#1

if(!myObj.myKey) myObj.myKey = someCostlyOperation();

方法#2

myObj.myKey = myObj.myKey || someCostlyOperation();

总结:

  • 方法#1检查myKey是否是假的。如果undefined,则会将其设置为 someCostlyOperation()

  • 方法 #2 没有条件,但总是重新分配myObj.myKey .如果为假,则将其设置为 someCostlyOperation()

性能

差异可能并不显著,但在嵌套循环中,此行被评估数万次,为了缩短执行时间并提高整体应用程序性能,每个小的优化都很重要。

我假设方法 #1 更快,因为它对方法 #2 所做的myObj.myKey进行相同的检查,但是,每次都没有无用地重新分配它。不过我可能是错的,因为我不知道 Javascript 解释器对这样的代码所做的所有内部优化(在我的情况下,它与 Node.js 一起运行)。

实现这一目标的最佳方法是什么?


编辑

Arnauld在评论中提出了第三种方法。在这里:

方法#3

!myObj.myKey && (myObj.myKey = someCostlyOperation());

它基本上是所有 3 种方法之间的联系。

(function(){
  var myObj = { };
  var time1,time2,testTime1,testTime2,testTime3,test1Wins=0,test2Wins=0,test3Wins=0,noWinner=0;
  function someCostlyOperation(){
    for(var i=0; i<100000; i++){
    }
    return {};
  }

  function method1(){
    if(!myObj.myKey) myObj.myKey = someCostlyOperation();
  }
  function method2(){
    myObj.myKey = myObj.myKey || someCostlyOperation();
  }
  function method3(){
    !myObj.myKey && (myObj.myKey = someCostlyOperation());
  }

  for(var i=0;i<10000;i++){
  delete myObj.myKey;
  time1 = performance.now();
  method3();
  time2 = performance.now();
  testTime1 = time2-time1;
  delete myObj.myKey;
  time1 = performance.now();
  method2();
  time2 = performance.now();
  testTime2 = time2-time1;
  delete myObj.myKey;
  time1 = performance.now();
  method3();
  time2 = performance.now();
  testTime3 = time2-time1;

  if(testTime1<testTime2 && testTime1<testTime3){
      test1Wins++;
  }
  else if(testTime2<testTime3 && testTime2<testTime1){
     test2Wins++;
  }
  else if(testTime3<testTime1 && testTime3<testTime2){
      test3Wins++;
  }
    else{
        noWinner++;
    }
  }
  console.log("test1Wins:",test1Wins);
  console.log("test2Wins:",test2Wins);
  console.log("test3Wins:",test3Wins);
  console.log("noWinners:",noWinner);
})();