有没有办法让静态/恒定的条件?

时间:2018-03-27 19:38:51

标签: javascript performance if-statement optimization branch-prediction

假设我有一个这样的代码段,

let arr = [{...},{...} ...]// huge array of objects;

arr.forEach(i => {
  if(someOtherProperty == "one") {
    ...
  } else if(someOtherProperty == "two") {
    ...
  }...

})

基本上,我在循环中有一个if-else-if梯形图。

条件不依赖于数组项。

我想知道是否可以在执行循环之前评估if条件,因为条件在整个循环运行期间是静态/恒定的

我能想到的几乎是

  1. 将循环保留在每个if / else块中。这样if条件只会执行一次,但我有更多的代码。
  2. 使用

    之类的对象
    let condition = {
      one: someOtherProperty == "one",
      two: someOtherProperty == "two",
      ...
    }
    

    并在 if(condition.one)等条件下使用它。

    请建议更好的方法来处理此类情况,以提高效率。

4 个答案:

答案 0 :(得分:2)

我认为在这种情况下,条件语句中的代码之间存在巨大差异,您可以使用以下方法使代码看起来更好:

let arr = [1, 2, 3, 4, 5];
let str = "one";
const conditions = {
  "one": function(item, index) {
    console.log("one", item);
  },
  "two": function(item, index) {
    console.log("two", item);
  }
}

arr.forEach(conditions[str]);

或者如果你想坚持基础,你也可以这样做:

let arr = [1, 2, 3, 4, 5];
let str = "one";
var one = function(item, index) {
  console.log("one", item);
};
var two = function(item, index) {
  console.log("two", item);
};
switch (str) {
  case "one":
    arr.forEach(one);
    break;
  case "two":
    arr.forEach(two);
    break;
}

答案 1 :(得分:0)

要保存代码重复,您可以执行一次条件检查,遍历循环,然后将其余代码放在函数中。

您还可以将循环迭代代码放在函数中并根据您在循环中执行的操作调用它。

let arr = [{...},{...} ...]// huge array of objects;

if(someOtherProperty == "one") {
    arr.forEach(i => { ...functionOnArray(); });
    functionOne();
} else if(someOtherProperty == "two") {
    arr.forEach(i => { ...functionOnArray(); });
    functionTwo();
}...

function functionOnArray(){ ... }
function functionOne(){ ... }
function functionTwo(){ ... }

答案 2 :(得分:0)

想到的最佳解决方案是使用功能方法。

let arr = [1,2,3,4,5,6,7,8,9]; // Huge array

let condFactory = (condition) => {
    if (condition === 'one') {
        console.log('This will only be called once, if condition==="one"',
                    'it will not be called for each element')
        return (item, index) => console.log('one (called for each element)', item, index);
    } else if (condition === 'two') {
        console.log('This will only be called once, if condition==="two"',
                    'it will not be called for each element')
        return (item, index) => console.log('two (called for each element)', item, index);
    }

    console.log('This will only be called once, if no condition matches',
                'it will not be called for each element')
    return (item, index) => console.log('No condition matched (called for each element)', item, index);
}

arr.forEach(condFactory(someOtherProperty));

对于es5:

var arr = [1,2,3,4,5,6,7,8,9]; // Huge array

var condFactory = function(condition) {
    if (condition === 'one') {
        console.log('This will only be called once, if condition==="one"',
                    'it will not be called for each element')
        return function(item, index) { console.log('one (called for each element)', item, index); };
    } else if (condition === 'two') {
        console.log('This will only be called once, if condition==="two"',
                    'it will not be called for each element')
        return function(item, index) { console.log('two (called for each element)', item, index); };
    }

    console.log('This will only be called once, if no condition matches',
                'it will not be called for each element')
    return function(item, index) { console.log('No condition matched', item, index); };
}

arr.forEach(condFactory(someOtherProperty));

这样,每个条件使用的函数将在循环开始之前确定,并用于循环内的每个元素。

你可以拉伸这个oneliner

arr.forEach(condFactory(someOtherProperty));

分成两行,看看为什么if ... else只被评估一次:

let functionBasedOnIfElse = condFactory(someOtherProperty); // Get the function based on your "someOtherProperty"
arr.forEach(functionBaseOnIfElse); // Pass reference to the function

如您所见,if ... else只会被评估一次。返回的函数if ... else将被传递给arr.forEach并为数组中的每个元素调用。

编辑:添加了默认返回。

Edit2 :已修正es5剪切

Edit3 :扩展案例以显示每个函数都应用于数组中的每个项目。

Edit4 :添加有关if ... else仅被评估一次的原因的更多信息。

Edit5 :添加一些console.log以显示将在哪个位置调用哪个部分。

答案 3 :(得分:-2)

您可以做的一件事是创建一个映射到数组的分支非匿名函数。例如。

f =  {(x => if (prop1 == "one") 
     { ...} 
     else if (prop2 == "two") 
     {...} )}

然后执行arr.forEach(i=> f(i))。这正是javascript的功能特性所实现的。

这与您尝试的操作大致相同。如果你试图聪明地partial application并将条件作为参数传递给该函数,它会更快。