When using higher order function of the Array API in javascript (forEach, map, filter, etc.) there are 2 means to pass "this" variable :
myArray.forEach(function(value) {
this.aContextualFunction();
}, this);
Or
var self = this;
myArray.forEach(function(value) {
self.aContextualFunction();
});
Which one is the better ? What are the pros and cons ?
Example: http://jsfiddle.net/TkZgX/
I always prefer the first one.
pro: no extra var declaration
con: maybe confusion as seen in the comments on this question..
When using higher order functions I prefer my functions not to make any assumptions about the callbacks it receives as arguments. In general, the more loosely coupled the code the better.
For example, say I write a higher order function for forEach
:
function forEach(array, callback, that) { // that is optional
var length = array.length;
for (var i = 0; i < length; i++)
callback.call(that, array[i], i); // pass the value and the index
}
Now say I want to use it:
Array.prototype.double = function () {
forEach(this, function (value, index) {
this[index] = 2 * value;
}); // oops, I forgot that
};
var array = [1, 2, 3];
array.double();
The above code will cause variables to leak into the global scope. Not a good thing. See the demo here: http://jsfiddle.net/8dad4/
What's the alternative? Remove the optional third parameter and use closures:
function forEach(array, callback) {
var length = array.length;
for (var i = 0; i < length; i++)
callback(array[i], i);
}
Not only is the code smaller, but there won't be any accidental global leaks (unless you use this
instead of the external that
like an idiot). Let's see an example:
Array.prototype.double = function () {
var that = this;
forEach(this, function (value, index) {
that[index] = 2 * value;
});
};
var array = [1, 2, 3];
array.double();
The demo is here: http://jsfiddle.net/8dad4/1/
Hmmm... that doesn't seem very enticing - I don't want to create a new variable. May we do something better? Yes, we sure can. This is the method I prefer (we still use the second forEach
function):
Array.prototype.double = function () {
forEach(this, function (value, index) {
this[index] = 2 * value;
}.bind(this));
};
var array = [1, 2, 3];
array.double();
The demo is here: http://jsfiddle.net/8dad4/2/
Wow, isn't this better? We combined both methods one and two. Advantages:
forEach
function doesn't assume anything. The code is more loosely coupled.that
. No closures needed.We can do this because the anonymous function passed to forEach
is a function expression. So we just append .bind(this)
to it and we're done.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With