问题
I was reading the Mozilla Documentation, but I don't understand the this which is passed into the function. Could anyone explain more about the usage of the this argument here?
function Counter() {
this.sum = 0;
this.count = 0;
}
Counter.prototype.add = function(array) {
array.forEach(function(entry) {
this.sum += entry;
++this.count;
}, this); //Why is this passed here?
};
var obj = new Counter();
obj.add([2, 5, 9]);
obj.count
// 3
obj.sum
// 16
回答1:
Per the Mozilla documentation:
thisArgOptionalValue to use as
thiswhen executing callback.
And also:
If a
thisArgparameter is provided toforEach(), it will be passed tocallbackwhen invoked, for use as itsthisvalue. Otherwise, the valueundefinedwill be passed for use as itsthisvalue. (Emphasis added)
What passing the thisArg to forEach does is bind the context. By default, this in forEach is the global window object, because undefined is used for this. Passing the context permits you to access things from that context.
In the prototype, this is the Counter constructor, and passing then allows you to set the context of which this is inside the forEach. So, instead of this being window inside the forEach, it is now Counter, and you can access variables such as this.sum otherwise not available due to the context.
回答2:
Since functions are self contained, your doing:
function x(){
this.test = 5
}
it only exists within the scope of the function.
If you start nesting functions as you have, if you want the scope to remain the same, you need to inform the function just that.
It is along the same lines of using the bind function.
function test(){
this.a = 4;
var y = function(){
this.a += 1;
}.bind(this);
}
if you didnt bind, for example, this.a would would be undefined, so the line: this.a += 1; would be the same as saying: this.a = undefined + 1
but when you bind, it will say: this.a = 4 + 1
回答3:
You can prevent the scoping by using arrow function in es6.
An arrow function expression has a shorter syntax compared to function expressions and does not bind its own this, arguments, super, or new.target.
function Counter() {
this.sum = 0;
this.count = 0;
}
Counter.prototype.add = function(array) {
array.forEach(entry=>{this.sum += entry;++this.count});
};
var obj = new Counter();
obj.add([2, 5, 9]);
console.log(obj);
This comes handy when the alternative methods available in es5 are using bind() to bind the this parameter, or using the thisArg that comes with forEach as already explained in the other answers.
来源:https://stackoverflow.com/questions/39813975/this-context-in-foreach