I’m looking through the MooTools source to try and understand its .implement() and .extend() utilities.
The definition of each refers to a function defined like this:
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;
};
};
However, I am having a tough time understanding what it does.
Can you explain how this function works and what it does?
overloadSetter
overloadSetter, together withoverloadGetter, are two function decorator methods. TheoverloadSetterfunction is used to transform functions that have the signaturefn(key, value)to functions that could accept object arguments, ie:fn({key: value}).In order to do this,
overloadSettermust wrap the original function. This wrapper function has the signaturefn(a, b)which is a shortcut forfn(key, value). This effectively becomes the new overloaded version of the original function.First thing this overloaded function does is check whether the passed
keyargument (a) is of the string type or not. If it’s not a string, the function assumes that we’re passing an object. So it iterates over each key-value pair in the object and applies the original function to it. If it’s a string, on the other hand, it simply applies the function to the values of theaandbarguments.Example
To illustrate, let’s say we have the following function:
In the first invocation, the
fnOverfunction is invoked with two arguments, a key and a value. When the function checks the type of theaargument value, it’ll see that it is a string. Therefore, it will simply invoke the originalfnOrigfunction:fnOrig.call(this, 'fruit', 'banana'). Our console output is'fruit: banana'.For the second invocation, the
fnOverfunction is invoked with an object argument. Since we passed an object instead of a string,fnOverwill iterate through the members of this object and invoke thefnOrigfunction for each one of them. Thus,fnOrigwill be invoked twice in this case:fnOrig.call(this, 'fruit', 'banana')andfnOrig.call(this, 'vegetable', 'carrot'). Our console output is'fruit: banana'and'vegetable: carrot'.Extras
Inside the wrapper function, you’ll see that there’s an check for the value of
usePlural. This is an argument for theoverloadSettermethod itself. If you set this value totrue, the new function will treat all arguments as object. This means that even if you pass a string key argument, it will still be processed as an object.The other thing, the
enumerablescode that preludes the actual method declaration, is there because it fixes an issue with some browsers wherein the nativeObjectmethods are not enumerated infor/inloops even if the object itself implements its own version of it.