The 'this' keyword in functions

2019-09-17 05:15发布

问题:

Taken from ejohn.org:

function katana(){ 
  this.isSharp = true; 
} 
katana(); 
assert( isSharp === true, "A global object now exists with that name and value." ); 

This comes out as true.

Could anyone explain this? Inside the function we see this.isSharp = true, doesn't that create an object which should have the propery isSharp, and its value would be true? (I would think the object is katana, since it calls the function, so katana.isSharp would be true). In other words, what exactly does the this refer to?

How come isSharp is created as an object?

回答1:

this is really wonky in JavaScript.

this is determined based on the context surrounding a function call, not as a property of the function. If a function is called like this:

f()

then this will refer to the global object. Adding a property to the global object is equivalent to adding a global variable, as you saw happen. If a function is called like this:

foo.f()

then this will refer to foo. Example:

> function printx() { console.log(this.x); }
> x = 300
> obj1 = {x: 20, printx: printx};
> obj2 = {x: 50, printx: printx};
> printx();
300
> obj1.printx();
20
> obj2.printx();
50

Finally, if a function is called like this:

new f()

then a new object is created, this refers to that new object, and the expression new f() evaluates to either that new object, or the object returned by f() if f() returns an object.

It's all in the spec. Very weird.



回答2:

You don't use new, so this is the global object (window) in the function.

katana();

is really

window.katana(); // the passed context is window

That's why the assertion isSharp===true, which tests in fact window.isSharp, returns true.

If you want to create a new instance of katana, use new katana(), and then this will be the new instance inside the function, leaving window.isSharp untouched.



回答3:

doesn't that create an object which should have the propery isSharp, and its value would be true?

No, because the function was not invoked as a constructor. If you had var obj = new katana(), then you'd get an object with an isSharp property. Otherwise, it's just a function call, so what should this be? JavaScript doesn't know, so it decides it's undefined and falls back to the global object (unless in strict mode).

Determining the value of this inside functions in JavaScript can be confusing, because it's determined dynamically, depending on how the function is called. The basic rules are, this will be the global object unless:

  • the function is called as an object method (then this will be the object), or
  • the function is called as a constructor, with the new operator (in which case this will point to the new object being constructed)

More details on MDN



回答4:

this refers to the object context of the call.

In your case it is window.katana(); So this refers to window