I get two different behaviors out of these, I was hoping someone could explain why.
function Test( id ) {
this.target = $(id);
this.children = [ $('<div/>').text("A"), $('<div/>').text("B") ];
}
// will add 0 1 A B
Test.prototype.addToTarget = function() {
this.children.forEach(this.target.append.bind(this.target));
};
// will add A B
Test.prototype.addToTargetEx = function() {
var target = this.target;
this.children.forEach(function(child){
target.append(child);
});
};
In the first version, you're binding the this
value, but forEach
passes 3 arguments to its callback, which are the item, the index and the original array.
In the second version, you're manually passing only the first argument given to the callback, and ignoring the last two.
So (for illustration of the issue) you can force your second version to behave like the first like this...
this.children.forEach(function(child, idx, arr){
target.append(child, idx, arr); // Passing all 3 args
});
Now it's clearer that .append()
is receiving 3 values on each iteration.
There's not really any way around this using .bind()
. If .append()
were made to only recognize the first argument passed, then it would work.
One thing you could do would be to create your own custom .bindN
method. Instead of being able to bind this
and individual arguments, it could bind this
and receive a "limiter" that will limit the number of arguments it's allowed to receive.
It could look like this:
Function.prototype.bindN = function(thisArg, n) {
var origFunc = this;
return function() {
return origFunc.apply(thisArg, Array.prototype.slice.call(arguments, 0, n));
}
};
Then use it like this:
this.children.forEach(this.target.append.bindN(this.target, 1));