MooTools的Function.prototype.overloadSetter()有什么作用?

Aus*_*yde 15 javascript mootools

我正在浏览MooTools源代码,试图了解它.implement().extend()实用程序.

每个的定义指的是这样定义的函数:

var enumerables = true;
for (var i in {toString: 1}) enumerables = null;
if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor'];

Function.prototype.overloadSetter = function(usePlural){
    var self = this;
    return function(a, b){
        if (a == null) return this;
        if (usePlural || typeof a != 'string'){
            for (var k in a) self.call(this, k, a[k]);
            if (enumerables) for (var i = enumerables.length; i--;){
                k = enumerables[i];
                if (a.hasOwnProperty(k)) self.call(this, k, a[k]);
            }
        } else {
            self.call(this, a, b);
        }
        return this;
    };
};
Run Code Online (Sandbox Code Playgroud)

但是,我很难理解它的作用.

你能解释一下这个功能是如何工作的以及它的作用吗?

小智 29

overloadSetter

overloadSetter与...一起overloadGetter,是两个函数装饰器方法.该overloadSetter函数用于将具有签名fn(key, value)的函数转换为可以接受对象参数的函数,即:fn({key: value}).

为此,overloadSetter必须包装原始功能.这个包装函数具有签名fn(a, b),这是一个快捷方式fn(key, value).这实际上成为原始函数的新重载版本.

这个重载函数的第一件事就是检查传递的key参数(a)是否属于字符串类型.如果它不是字符串,则该函数假定我们正在传递一个对象.因此,它迭代对象中的每个键值对并将原始函数应用于它.另一方面,如果它是一个字符串,它只是将函数应用于ab参数的值.

为了说明,假设我们有以下功能:

var fnOrig = function(key, value){
    console.log(key + ': ' + value); 
};

var fnOver = fnOrig.overloadSetter();

fnOver('fruit', 'banana');
fnOver({'fruit': 'banana', 'vegetable': 'carrot'});
Run Code Online (Sandbox Code Playgroud)

在第一次调用中,fnOver使用两个参数(键和值)调用该函数.当函数检查a参数值的类型时,它会看到它是一个字符串.因此,它只需调用原始fnOrig函数:fnOrig.call(this, 'fruit', 'banana').我们的控制台输出是'fruit: banana'.

对于第二次调用,fnOver使用object参数调用该函数.由于我们传递了一个对象而不是一个字符串,因此fnOver将遍历该对象的成员并fnOrig为每个对象调用该函数.因此,fnOrig在这种情况下将被调用两次:fnOrig.call(this, 'fruit', 'banana')fnOrig.call(this, 'vegetable', 'carrot').我们的控制台输出是'fruit: banana''vegetable: carrot'.

附加功能

在包装函数中,你会看到有一个值的检查usePlural.这是overloadSetter方法本身的一个参数.如果将此值设置为true,则新函数会将所有参数视为对象.这意味着即使传递字符串键参数,它仍将作为对象处理.

另一件事,enumerables即实际方法声明之前的代码,因为它解决了某些浏览器的问题,即在对象本身实现其自身版本的情况下,本机Object方法不会在for/in循环中枚举.

  • 虽然这有点不太可能改变,但我应该指出这是一个私有/内部方法,并且编写依赖于API的代码可能经得起时间的考验(暂时在1.3中工作) (6认同)