JavaScript class and call context

Can someone help me explain why the first example works and the second does not.

Example 1:

// Define a class function Foo(name) { var self = this; this.name = name; this.greeting = function() { console.log('Hello ' + self.name); } } var foo = new Foo('foo'); foo.greeting(); var greeting = foo.greeting; greeting(); 

Output:

 Hello foo Hello foo 

Example 2:

 // Define a class function Foo(name) { this.name = name; } // Greeting Foo.prototype.greeting= function () { console.log('Hello ' + this.name); } var foo = new Foo('foo'); foo.greeting(); var greeting = foo.greeting; greeting(); 

Output:

 Hello foo Hello undefined 

My assumption would be that the first example uses closure, so it retains a reference to the local variable name , but the second example is missing, and since the greeting() method is called without an object context, it defaults to undefined .

+4
source share
4 answers

Many answers, all with useful and correct information, but none of them explains the correct behavior.

In the first example, it only registers Hello foo both times because you create a self variable that references the this object. This self variable is then closed in your greeting function . Therefore, you can call this function self.name you want, it will always have access to self.name , not this.name , so it will always be the same.

You do not do this in your prototype example. There you directly access this.name , and then it really matters how to call the function (see @lwburk's answer).

So, even if you call the first example, for example

 foo.greeting.call( window ); 

it will still access the private variable self and log Hello foo .

+6
source

There are four ways to call a function in JavaScript, each of which changes the value of this inside the function:

  • Like calling a global function : greeting() . The value of this is the global window object (in browsers).

  • As a method for some object: foo.greeting() . The value of this is an instance of the object on the left side of the statement . ( foo ).

  • As a constructor : new greeting() . The value of this is a new object that is created and implicitly returned from the function. This is used to create new objects.

  • Using call or apply : greeting.apply(someVal, someArgs) . The value of this is the object passed as the first argument ( someVal ).

Any function can be performed in any of these four ways (although not all functions must be performed in some of them).

In the first case, you make a method call:

 var foo = new Foo('foo'); foo.greeting(); 

... therefore this is foo inside the function. In the second case, you make a global function call:

 var greeting = foo.greeting; greeting(); 

... therefore this is a window inside a function.

Edit: Note @jAndy, which points out a more important issue in this case, which is that greeting closes over self in the first example (no matter how it called) but not in the second (which then does as the function called relevant).

+5
source

This permission is delayed until runtime in JavaScript.

By setting foo.greeting to greeting and then executing greeting() , you execute greeting() in a global context; in which this points to window if you are not working in strict mode and not in your Foo instance. Because of this, inside greeting() it is looking for window.name ; and return undefined.

See the this in the MDC for a more detailed explanation.

+2
source

the second greeting () is executed in the global scope, so this is a window object (the same volume in which the function is executed, and window.name is undefined). It works again if you pass the context through apply() or call() , for example.

 var greeting = foo.greeting; greeting.apply(foo); 
0
source

Source: https://habr.com/ru/post/1391664/


All Articles