0

我想在 javascript 中动态编辑我的 if else 语句。

因此,在使用一个 if 语句之后,它可以被删除。我知道这可能是不可能的,但是在网上搜索失败后,我的好奇心求我问。

例如:

if (x > 200 && x % 25 === 0) {
  doSomething1();
} else if (x > 300 && !inRange) {
  doSomething2();
} else if (x > 400 && x % 7 === 0) {
  doSomething3();
}

此循环中有八个 if else 语句。循环确定要创建的对象。在几分钟内创建了 2000 个对象。如果平均而言,我们在第四条语句中断之前到达它,那么仅在这一组语句中执行了 8,000 次计算。

我想再次简化脚本以提高速度,好奇我们是否可以在不使用单独函数等的情况下真正动态地编写 javascript。在 if 语句失败后,通常不再需要它。我想下一个语句可以包含动态删除其前身的代码。这可能会节省 3 或 4 千次计算 - 我知道这不是很大,但考虑到还有很多其他事情正在发生,值得考虑。

有没有办法动态删除它们,或者是否有人有任何技巧或模式?

另外,即使这在 js 中不可用,这会被称为什么?

4

6 回答 6

2

为什么要动态删除它们?动态更改代码是不必要的,而且在这种情况下,一袋蠕虫会过度使用。你应该使用一个标志。

我将分别回答您是要跳过一大组 if 语句还是单个 if 语句。

前言

正如您问题的评论中提到的,运行分析以确保您知道性能问题在哪里!

您提到您不喜欢简单地使用布尔标志来使 if 语句不在您的答案中运行。这很好,这是人们通常会做的事情。这不应该是一个实际的性能问题,并且分析可能会显示您的性能问题存在于其他地方。如果他们不这样做,并且这个布尔标志检查确实是您的瓶颈 - 您会遇到更大的问题,例如对 JavaScript 代码的期望过高,或者您没有正确使用分析工具,或者误解了它的结果。

如果您试图避免运行 if 语句的主体或其条件,那么与布尔标志检查本身相比,这些对您来说是更大的性能问题。

用于跳过一大组 if 语句

将一堆if语句包装在一个条件中。

if (runBunchOfIfStatements) {
    // all those if statements here
}

当您不想运行这些 if 语句时,请将runBunchOfIfStatements标志设置为 false(当然,您可能应该选择一个比这更有意义的名称)。

也就是说,8 或 9 个 if 语句是一个代码长度问题,而且很可能对性能问题毫无意义——除非那些 if 语句碰巧涉及非常密集的检查。如果您只是因为有很多if检查而担心,那么您可能找错地方了。

对于单个 if 语句

假设您只有一个要跳过的 if 语句。您的答案中有此代码:

} else if (x > 300 && !doneSomething2) {
  doSomething2();
  doneSomething2 = 1;
}

这可以。你只是做一个小检查:见前言。在其他地方寻找您的性能问题。可以稍微重写它以更严格地遵循约定(我即将达到),但在这种情况下,更改的影响可以忽略不计。

让我们假设这里实际上存在性能问题。假设x > 300你正在做一些更密集的事情,而不是检查calculateSeveralSquareRoots()。通常,您确实采用这种方法,但您重新排列它是这样的:

} else if (needCalculations && calculateSeveralSquareRoots() {
    // do stuff
    needCalculations = false;
}

这里的区别是标志needCalculations是第一位的,而不是第二位的。JavaScript 的比较运算符有短路求值。这意味着当评估时a && b,如果a为假,b甚至永远不会被检查——我们已经知道结果将是假的。如果标志先出现,这意味着calculateSeveralSquareRoots()永远不会运行,并且您可以节省检查时间。

如果标志位居第二,那么您可能会在该函数上浪费大量时间,因为该标志可能几乎总是解析为假。

因此,在您的原件中,您可以在评估之前x > 300使用标志,只是为了遵循惯例。但是同样......如果这样的 if 语句对您来说是一个真正重要的性能问题,那么您有更大的问题。

于 2013-04-30T01:28:46.073 回答
2

No. And the need for such would indicate poor design.

You should use a conditional expression to determine when which code segment should be run, as you mention. If you pass a certain threshold within your code after which you no longer want a condition to be executed in your loop, why not simply break the loop and have a new code block handling the doSomethingElse clause. If you're using setInterval, that's the point at which you would call clearInterval, and then trigger some new action if necessary. Anyway, running a single (or even a few) simple conditional statement doesn't add much overhead, and isn't likely to be the limiting factor in your optimization anyway.

于 2013-04-30T01:29:50.073 回答
2

忽略这样一个事实,即我怀疑这是现代浏览器中的一个瓶颈,即 JIT JavaScript(CPU 非常擅长预测分支),如图所示,因为即使在编译后具有智能预测的大型迭代中,简单的数字比较也不会很昂贵。

您可以通过注入不同的函数来做到这一点:

checker: function(x) {
    if (x > 200) {
        doSomething1();
    }
    else if (x > 300) {
        doSomething2();
    }
    else if (y > 400) {
        doSomething3();
    }
}

可以改为

checker: function(x) {
    if (x > 200) {
        doSomething1();
    }
    else if (x > 300) {
        doSomething2();
        this.checker = smallerChecker;
    }
    else if (y > 400) {
        doSomething3();
    }
}

function smallerChecker(x) {
    if (x > 200) {
        doSomething1();
    }
    else if (y > 400) {
        doSomething3();
    }
}

从根本上说,您只需要使行为可注入,然后根据您认为合适的方式对其进行更改。就像我上面所做的那样,通过替换进行彻底检查的函数(功能方式),或者启用一个对象来替换它(OO方式)。

于 2013-04-30T01:42:40.890 回答
1

按可能性顺序对它们进行排序(因此,如果 >400 是最常见的,则首先检查它,如果 x<200 是下一个最常见的,则检查它,等等。示例代码按边界增加的顺序排列。

接下来,你的代码没有显示它,你只是暗示它,这是一个循环。(如果它不是一个循环,那么这不是一个感兴趣的性能问题)你可以尝试像 Duff 的设备这样的花哨的循环。

找出可以更改哪些代码以使用更多本机 API 将产生神奇的影响,而像这样的代码优化可能只会产生微小的差异。

于 2013-04-30T02:11:15.500 回答
0

您可以创建如下方法并创建动态条件

function buildCond(lhv1,rhv1,lhv2,rhv2) 
{
    var condition1,condition2;
    condition1 = condition2 = '';
    if(rhv1 !== -1){
        condition1 =  lhv1 + " == " + rhv1 + " && ";
    } 
    if(rhv2 !== -1){
        condition2 =  lhv2 + " == " + rhv2 + " && ";
    }
    return condition1 + condition2;
}

And then call this method with eval to execute

if(eval(buildCond(var1,value1,var2,value2)) === true){
    //do stuff
}
于 2013-12-12T19:02:41.010 回答
0

如果您希望它是动态的,您可以始终拥有与操作相关联的条件集合,并且一旦执行,这些条件就会从集合中删除。但是,我怀疑它会导致更快的代码执行,但您必须创建一个jsperf测试才能确定。

演示:http: //jsfiddle.net/a2ZEj/1/

function doSomethingA() {}
function doSomethingB() {}

var doOperation = (function doOperation() {
    var operations = [
        {
            check: function (someArg) {
                return someArg > 100;
            },
            exec: doSomethingA
        },
        {
            check: function (someArg) {
                return someArg > 100 && someArg < 200;
            },
            exec: doSomethingB
        }
    ];

    return function (someArg) {
        var i = 0,
            len = operations.length,
            item;

        for (; i < len; i++) {
            if ((item = operations[i]).check(someArg)) {
                item.exec();
                operations.splice(i, 1);
                console.log('executed ' + item.exec.name);
                return;
            }
        }
    };
})();

doOperation(101); //calls doSomethingA
doOperation(101); //calls doSomethingB
doOperation(101); //does nothing
于 2013-04-30T01:55:12.640 回答