【问题标题】:How To Refactor If-else Code Segment?如何重构 If-else 代码段?
【发布时间】:2012-12-11 13:24:30
【问题描述】:

我正在使用 Html5-js-jquery 开发 win8(metro 风格)应用程序。 我有这个代码段;

    GetBoutiqueDetail: function (boutiqueId, options) {
        if (IsUserLogin()) {
            //different job A
        } else {
            ShowLoginPanel(undefined);
        }
    },
    GetProductDetail: function (boutiqueId, productId, options) {
        if (IsUserLogin()) {
            //different job B
        } else {
            ShowLoginPanel(undefined);
        }
    },
    AddBasket: function (productId, productVariantId, quantity, options) {
        if (IsUserLogin()) {
            //different job C
        } else {
            ShowLoginPanel(undefined);
        }
    },....

。大约 20 个函数应该检查用户是否登录。 我应该调用类似于“Library.GetBoutiqueDetail();”的函数

所以我的问题很简单,我如何重构该代码以删除这些 if-else 部分?

【问题讨论】:

  • 为什么这些函数都是大写的?他们似乎不是构造函数。

标签: javascript microsoft-metro


【解决方案1】:

试试这样的:

checkLogin: function( action, actionArgs ) {

    if( IsLogin ) {

        return action.apply(this, actionArgs );
    }

    ShowLoginPanel();
},

GetBoutiqueDetail: function (boutiqueId, options) {

    //different job A
},
GetProductDetail: function (boutiqueId, productId, options) {

    //different job B
},
AddBasket: function (productId, productVariantId, quantity, options) {

    //different job C
}

【讨论】:

    【解决方案2】:

    这个对象映射怎么样:

    var objMap = {  
      "GetBoutiqueDetail":fnJobA,
      "GetProductDetail":fnJobB,
      "AddBasket":fnJobC}
      ....
    }
    
    if (loggedIn) {
      objMap[task]();
    }
    else {
      doLogin();
    }
    

    【讨论】:

    • 所示示例没有任何参数。因此解决方案。否则,也可以使用闭包。
    • 问题作者确实在函数GetBoutiqueDetail中有参数。我也没有发现job:fnJobA 很明显? (不过我喜欢地图解决方案,只是在寻找改进,别担心:D)
    • 仔细看后,这确实行不通。您应该放置一个关联数组(对象)而不是带有对象的数组。您不能将其用作这样的地图。 objMap[task]() 不起作用..
    • @EricG:让我再测试一下。我以前用过。
    • 你应该把它改成var objMap = { "KeyA": funcA, "KeyB": funcB }objMap[key]() 或者var objMap = { "KeyA": { job: funcA }, "KeyB": { job: funcB } }objMap[key].job()(虽然最后一个没有添加任何东西)
    【解决方案3】:

    您始终可以将通用代码包装到更高范围的函数中,并从库函数中调用它 - 例如:

    //Higher scope:
    function CheckForLogin(executionFunction)
    {
       if(IsLogin) {
          executionFunction();
       } else {
          ShowLoginPanel(undefined);
       }
    };
    
    
    GetBoutiqueDetail: function (boutiqueId, options) {
        CheckForLogin(//different job A)
    }
    

    different job 'N' 作为匿名函数传递给CheckForLogin

    【讨论】:

      【解决方案4】:

      在 Javascript 中你可以从一个函数返回来结束它,所以 f.ex:

      GetProductDetail: function (boutiqueId, productId, options) {
          if (!IsLogin) return ShowLoginPanel();
          // different job...
      }
      

      尽管如此,您仍然会有一些重复的代码。另一种选择是定义更高级别的功能。比如:

      var loginOrAction = function() {
          if (!IsLogin) return ShowLoginPanel();
          var args = [].slice.call(arguments);
          Library[args.shift()].apply(Library, args);
      }
      
      loginOrAction('GetBoutiqueDetail', boutiqueId, options);
      

      【讨论】:

      • 您只是跳过了else。不过没关系。
      【解决方案5】:

      使用三元运算符

      (IsLogin) ? jobA() : ShowLoginPanel(undefined)
      

      【讨论】:

      • 那不统一程序(不避免代码冗余)。
      • 问题不是“代码统一”... OP 想要摆脱 if / else -> 三元在很多情况下都很有用。
      • 去掉'if-else'的目的不是为了避免看到字母,而是为了避免所有20个函数中的重复代码。因此,他可能会对检查这一点的标准化方式感到满意。你怎么看?
      • 我完全同意。我只是想向 OP 展示 if/else 的替代方案。
      • 好的。我不争辩说你严格回答了这个问题,但人们不应该认为这是正确的重构,不幸的是我会因此保留反对意见。感谢您的贡献:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-27
      相关资源
      最近更新 更多