【问题标题】:Is it possible to use method chaining assigning strings in Javascript?是否可以在Javascript中使用方法链接分配字符串?
【发布时间】:2017-05-05 22:16:59
【问题描述】:

我想通过 JavaScript 和 AngularJS 使用方法链接语法。我分配数组和字符串。

此代码有效:

$mdDateLocaleProvider
     .shortDays = ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sá']
     .msgCalendar = 'Calendario'
;

此代码不起作用:

$mdDateLocaleProvider
     .shortDays = ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sá']
     .msgCalendar = 'Calendario'
     .msgOpenCalendar = 'Abrir calendario'
;

我认为 msgOpenCalendar = 'Abrir calendario' 语句由于字符串分配而失败。

我的解决方案:

$mdDateLocaleProvider
     .shortDays = ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sá']
     .msgCalendar = 'Calendario'
;
$mdDateLocaleProvider
     .msgOpenCalendar = 'Abrir calendario'
;

为什么分配字符串时出现问题,而不是数组?

【问题讨论】:

  • “此代码有效” - 并非您想象的那样。

标签: javascript angularjs variable-assignment method-chaining


【解决方案1】:

之所以叫method链接是有原因的,它用于链接methods,而不是变量赋值。

在方法链接中,您只是在方法(函数)的末尾返回对象实例(可变或新的不可变对象),因此您可以“立即”调用下一个函数。

它“起作用”的原因是 JS 中的数组是一个对象,因此您只需在分配给 shortDays 属性的数组上放置一个 msgCalendar 属性。

基本上,你所取得的成就是:

var shortDays = ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sá'].msgCalendar = 'Calendario';
// here shortDays actually equals to 'Calendario', because it is like writing a = b = 2.
$mdDateLocaleProvider.shortDays = shortDays;
$mdDateLocaleProvider.msgOpenCalendar = 'Abrir calendario';

【讨论】:

  • 我相信他实际上实现的是$mdDLP.shortDays = 'Calendario',而阵列在此过程中丢失了。
【解决方案2】:

您不能像您正在做的那样将方法链接与直接分配一起使用。正如 Ron 所解释的,您认为它所做的并不是它实际所做的。

解决此问题的一种方法是实现Builder pattern,它允许您基于链接它们的setter 方法来创建对象。

【讨论】:

    【解决方案3】:

    您不能使用链接,但是由于您在问题中包含了 angularjs 标记,您可能想看看使用angular.extend

    angular.extend($mdDateLocaleProvider, {
         shortDays: ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sá'],
         msgCalendar: 'Calendario',
         msgOpenCalendar: 'Abrir calendario'
    });
    

    这将具有更新三个属性的预期效果,如果您想调用任何方法,您甚至可以在结果上使用方法链。

    【讨论】:

      【解决方案4】:

      你想要assign()

       Object.assign($mdDateLocaleProvider, {
            shortDays : ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sá']
            msgCalendar : 'Calendario'
            msgOpenCalendar : 'Abrir calendario'
       });
      

      它会立即为您设置所有内容。


      如果您需要实际链接,比如设置 shortDays,调用一个函数,然后设置 msgCalendar,试试我的 shim。
      这也适用于 assign 不起作用(设置 DOM onclicks 或 innerTexts),或者您需要调用不链接的函数。

       wrap($mdDateLocaleProvider)
            .set('shortDays'      , ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sá'])
            .set('msgCalendar'    , 'Calendario')
            .set('msgOpenCalendar', 'Abrir calendario')
       ;
      

      只需拨打wrap() 即可。

      wrap = (obj) => (Object.defineProperty(obj,
                  'define', {value:(name, options) => (Object.defineProperty(obj, name, options))})
          .define('assign', {value:(props)         => (Object.assign(obj, props))                })
          .define('set'   , {value:(name, value)   => { obj[name] = value; return obj; }         })
          .define('invoke', {value:(name, ...args) => { obj[name](...args); return obj; }        })
      );
      

      Demo

      let bob = {
          hello  : 'there',
          chains : () => {bob.I_RAN = true; return bob;},
          doesnt : (arg1, arg2) => {bob.I_RAN_ALSO = [arg1, arg2]; return null;}
      };
      wrap(bob)
          .set('oh', 'my')
          .chains()
          .invoke('doesnt', 'works', 'anyway')
          .assign({more:7, stuff:null})
      ;
      for (let item of Object.keys(bob))
            console.log(`'${item}' : ${bob[item]}`);
      

      输出:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-06-11
        • 2012-02-21
        • 2016-12-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-10
        相关资源
        最近更新 更多