【问题标题】:Convert ternary conditional operators into if statements?将三元条件运算符转换为 if 语句?
【发布时间】:2012-02-12 01:42:41
【问题描述】:

使用看起来像这样的缩小代码,

f&&!f.error?k.button.b==k.button.c.G?k.button.Q(b,e,f,c,d):k.button.b==k.button.c.o&&k.button.P(b,e,f,c,d):(console.error(f),f=f.error.message||chrome.i18n.getMessage("error_tooltip"),k.button.v(b.id,f),d({action:"error"}))

是否有一种自动化工具可以将那一行条件运算符转换为一系列 if 语句?

示例 1:

来自

(i < 0 ? function1() : function2())

if (i < 0) {
    function1();
} else {
    function2();
}

示例 2:

来自

(i < 0 ? function1() : (i === 0 ? function2() : function3()))

if (i < 0) {
    function1();
} else {
    if (i === 0) {
        function2();
    } else {
        function3();
    }
}

【问题讨论】:

  • 你能提供一个更简短的例子,并包括一个你想要的结果的例子吗?此外,这几乎与语言无关,因为这样的工具必须能够解析您正在使用的特定语言(看起来像 Javascript)。
  • @ldiqual,这些格式化程序都没有将条件运算符转换为 if 语句。他们只是添加空格。

标签: javascript syntax if-statement conditional-operator


【解决方案1】:

来自

f&&!f.error?k.button.b==k.button.c.G?k.button.Q(b,e,f,c,d):k.button.b==k.button.c.o&&k.button.P(b,e,f,c,d):(console.error(f),f=f.error.message||chrome.i18n.getMessage("error_tooltip"),k.button.v(b.id,f),d({action:"error"}))

if (f && !f.error)
{
    if (k.button.b == k.button.c.G)
    {
        k.button.Q(b, e, f, c, d)
    }
    else
    {
        k.button.b == k.button.c.o && k.button.P(b, e, f, c, d)
    }
}
else
{
    (console.error(f), f = f.error.message || chrome.i18n.getMessage("error_tooltip"), k.button.v(b.id, f), d(
    {
        action: "error"
    }))
}

使用这个(然后是 JSBeautifier):

/*jslint browser: true, vars: true, white: true, maxerr: 50, indent: 4 */
(function (console)
{
    "use strict";

    function transform(string)
    {
        var questionMark = string.indexOf("?");
        var colon = string.indexOf(":", questionMark);

        if (questionMark === -1 || colon === -1)
        {
            return string;
        }

        var condition = string.substring(0, questionMark);
        var expressions = string.substring(questionMark + 1, string.length);
        var trueExpression = null;
        var falseExpression = null;

        console.log("expressions: " + expressions);

        // While looking in pairs, find the location where the colon occurs before the question mark.
        questionMark = expressions.indexOf("?");
        colon = expressions.indexOf(":");
        while ((questionMark !== -1 && colon !== -1) && (questionMark < colon))
        {
            questionMark = expressions.indexOf("?", questionMark + 1);
            colon = expressions.indexOf(":", colon + 1);
        }

        console.log("\t" + "questionMark: " + questionMark);
        console.log("\t" + "colon: " + colon);

        trueExpression = expressions.substring(0, colon);
        falseExpression = expressions.substring(colon + 1, expressions.length);

        console.log("condition: " + condition);
        console.log("trueExpression: " + trueExpression);
        console.log("falseExpression: " + falseExpression);

        console.log("-");

        return ("if (" + condition + ") {\n" + transform(trueExpression) + "\n} else {\n" + transform(falseExpression) + "\n}");
    }

    function unittest()
    {
        console.log(transform("(i < 0 ? function1() : function2())"));
        console.log("---");
        console.log(transform("i < 0 ? function1() : function2()"));
        console.log("---");
        console.log(transform("i < 0 ? function1() : i === 0 ? function2() : function3()"));
        console.log("---");
        console.log(transform("i > 0 ? i === 1 ? function1() : function2() : function3()"));
        console.log("---");
        console.log(transform("i > 0 ? i === 1 ? function1() : i === 2 ? function2() : function3() : function4()"));
        console.log("---");
        console.log(transform("i > 0 ? i === 1 ? function1() : i === 2 ? function2() : function3() : i === 0 ? function4() : function5()"));
        console.log("---");
        console.log(transform("f&&!f.error?k.button.b==k.button.c.G?k.button.Q(b,e,f,c,d):k.button.b==k.button.c.o&&k.button.P(b,e,f,c,d):(console.error(f),f=f.error.message||chrome.i18n.getMessage(\"error_tooltip\"),k.button.v(b.id,f),d({action:\"error\"}))"));
    }

    unittest();
}(window.console));

【讨论】:

  • 请在某个网站上托管这个!
【解决方案2】:

babel-plugin-transform-ternary-to-if-else

不知道是不是太晚了,这个问题毕竟有五年了。

我昨天遇到了完全相同的问题,并设法建立了一个 babel 插件来将条件表达式转换为 if-else 语句。它有一个非常直接的名称:babel-plugin-transform-ternary-to-if-else

重要提示:我确实说过表达式陈述,我们稍后会回复它们。

示例

这里我将两个示例代码作为输入,并使用插件运行它们。

// case 0: input
(i < 0 ? function1() : function2())

// case 0: output
(function () {
  if (i < 0) {
    return function1();
  }

  return function2();
})();

// case 1: input
(i < 0 ? function1() : (i === 0 ? function2() : function3()))

// case 1: output
(function () {
  if (i < 0) {
    return function1();
  }

  return function () {
    if (i === 0) {
      return function2();
    }

    return function3();
  }();
})();

很棒?

你可能会想:嗯……没那么多。所有这些IIFE(立即调用函数表达式)是怎么回事?

IIFE

实际上需要 IIFE。因为,正如我在开头所说的,条件表达式是表达式,if 语句是语句。

表达式可以是语句的一部分,这是肯定的。但是一个语句可以成为另一个语句的一部分吗? 不可以,除非包裹在 IIFE 中

当然,作为一种特殊情况,一个简单的表达式语句可以替换为另一个 if 语句,例如a1() ? a2() : a3(); 可以替换为 if (a1()) {a2();} else {a3();}。但这并不适用于所有情况。

所以,我们来了,IIFE。

未来

好消息是,当do expressions proposal 成为 ECMAScript 规范时,我们将不再像 IIFE 那样冗长。

事实上,babel-plugin-syntax-do-expressions 转换了do expressions into conditional expressions,这意味着它们是彼此完全替换

链接

babel-plugin-transform-ternary-to-if-else

do expressions proposal

babel-plugin-syntax-do-expressions

【讨论】:

    猜你喜欢
    • 2021-07-09
    • 1970-01-01
    • 2017-08-26
    • 1970-01-01
    • 2018-10-25
    • 1970-01-01
    • 2017-05-30
    • 2019-10-08
    • 2018-12-26
    相关资源
    最近更新 更多