简体   繁体   中英

Why 'this' points to window inside a function when apply() or call() is being called?

I'm reading Nicholas Z.Zakas' Professional JavaScript for web developer 3rd edition and inside the Reference types chapter I got a bit confused at the function type part.

function sum(num1, num2){
return num1 + num2;
}

function callSum1(num1, num2){
return sum.apply(this, arguments);
}

alert(callSum1(10,10)); //20

He says:

"In this example, callSum1() executes the sum() method, passing in this as the this value (which is equal to window because it's being called in the global scope) and also passing in the arguments object."

I understand what he says, but I don't understand the why. This supposed to point to the function doesn't it? Now I'm confused that it's pointing to the window because it's being called in the global scope ..

Can someone be kind to explain it to me? :)

I'm not sure if I will or I have to use this technique later, but I want to make sure I understand it, especially the this part. More details about this and its usage will come in the OOP section, but it's now an interesting question.

Thanks in advance!

The value of this depends on how you call a function.

If you call a function using call or apply then the value of this will be the first argument to that function.

Here you have sum.apply(this, arguments); so it will pass the current value through. As usual, that value is determined by how you call the function.

Since you call callSum1(10,10) with no context, this will be window .

(If you were in strict mode, it would be undefined . If you weren't in a browser, it would be whatever the default object of the JS environment you were using was).

Here:

alert(callSum1(10,10)); //20

...you're calling callSum without doing anything to set this during the call, and so this is defaulted to the global object ( window , on browsers). (In loose mode; in strict mode, this would have been undefined .)

Since you're then using apply and passing that same this into it:

return sum.apply(this, arguments);

...naturally the global object is also used when calling sum .

I understand what he says, but I don't understand the why. This supposed to point to the function doesn't it?

No, this almost never refers to functions. (It can, of course, it just very rarely does.)

Now I'm confused that it's pointing to the window because it's being called in the global scope ..

It's not because it's being called in the global scope; it would be the same if it were being called from inside a function. What matters isn't where the call occurs, but how . Any time you call a function without doing anything to set this , in loose mode, this during the function call will be the global object. It doesn't have to be at global scope; what matters is how you call the function.

The rule is actually a lot simpler than people make it out to be: If you call a function without doing anything to set this , during the call, this will be the global object (in loose mode) or undefined (in strict mode). Here are the things you can do to set this during a function call:

  1. Call the function as part of an expression getting the function from a property on an object. For example, foo.bar(); retrieves a reference to the function from the bar property on foo , then calls bar . Because we did it that way, during the call to bar , this refers to foo .

  2. Call the function using .call or .apply ; this will be what you pass in the first argument. (In loose mode, if you pass undefined , null , or a non-object in the first argument, during the call this will be the global object. In strict mode, it'll be what you pass.)

  3. Call a bound function. That's a function created via Function#bind (an ES5 feature). Bound functions have this "baked into" them.

More (on my blog) :

Under the Window object part ~20 pages later, I'm reading this: "As mentioned previously, the this value is equivalent to the Global object when a function is executed with no explicit this value specified (either by being an object method or via call() / apply() )." :)

Maybe I didn't get it before, but now it's clear with his words as well. By the way, the book is awesome! Now with Math object I can understand much more the apply() method, too.

var values = [1,2,3,4,5,6];
var max = Math.max.apply(Math, values);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM