简体   繁体   English

是否可以在 Javascript 中使用方法链分配字符串?

[英]Is it possible to use method chaining assigning strings in Javascript?

I want to use method chaining syntax using JavaScript and AngularJS.我想使用 JavaScript 和 AngularJS 使用方法链语法。 I assign arrays and strings.我分配数组和字符串。

This code works:此代码有效:

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

This code doesn't work:此代码不起作用:

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

I think the msgOpenCalendar = 'Abrir calendario' sentence is failing due to the string assignment.我认为msgOpenCalendar = 'Abrir calendario'句子由于字符串分配而失败。

My solution:我的解决方案:

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

Why is there a problem assigning a string but isn't with an array?为什么分配字符串时出现问题,但分配数组时没有问题?

The name is method chaining for a reason, it is used to chain methods , not variable assignments.名称是方法链接是有原因的,它用于链接方法,而不是变量赋值。

In method chaining, you are simply returning the object instance (of a mutable or a new immutable object) in the end of the method (function), so you can call the next function "right away".在方法链中,您只是在方法(函数)的末尾返回对象实例(可变或新的不可变对象),因此您可以“立即”调用下一个函数。

The reason it "works" is that an array in JS is an object, so you simply placed a msgCalendar property on the array that you assigned to shortDays property.它“作品”的原因是,在JS数组是一个对象,所以你只需放置一个msgCalendar您分配到阵列中财产shortDays财产。

Basically, what you achieved is:基本上,你取得的是:

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';

You cannot use method chaining with direct assignments like you're doing.你不能像你正在做的那样使用直接赋值的方法链。 As explained by Ron, what you think it does is not what it's actually doing.正如 Ron 所解释的,你认为它所做的并不是它实际在做的。

A way of working around this is implementing the Builder pattern that would allow you to create objects based on chaining their setters methods.解决此问题的一种方法是实现Builder 模式,该模式允许您基于链接它们的 setter 方法来创建对象。

You cannot use chaining, but as you included the angularjs tag in the question, you probably want to look at using angular.extend :您不能使用链接,但是当您在问题中包含 angularjs 标签时,您可能想要查看使用angular.extend

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

which will have the desired effect of updating the three properties and you can even use method chaining on the result if you want to call any methods.这将具有更新三个属性的预期效果,如果您想调用任何方法,您甚至可以对结果使用方法链。

You want assign() .你想要assign()

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

Which will set everything at once for you.这将为您立即设置一切。


If you need to actually chain say like maybe set shortDays , call a function, then set msgCalendar , try my shim.如果您需要实际链接,例如可能设置shortDays ,调用一个函数,然后设置msgCalendar ,试试我的垫片。
This will also work for when assign doesnt work (setting DOM onclick s or innerText s), or you need to call a function that doesn't chain.这也适用于assign不起作用(设置 DOM onclick s 或innerText s),或者您需要调用不链接的函数。

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

Simply call wrap() and away you go.只需调用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]}`);

Output:输出:
在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM