Strange value for object "this"

Regarding this code:

var name = "Jaguar"; var car = { name:"Ferrari", getName:function(){ return this.name; } }; alert((car.getName = car.getName)()); 

Exit: Jaguar .

Why does the this object correspond to Window , and not the object contained in the variable car ?

It seems that the fact of reassigning the function of the object in itself leads to the loss of assignment of this object when the function is called ...

I'm trying to guess: is there some kind of mechanism (using a variable or another) that monitors the non-return of the object function, so if this situation happens, this mechanism will prevent the assignment of the this as usual (as equal to the object)?

+4
source share
4 answers

The reason is pretty subtle: this in JavaScript is completely determined by how the function is called. In order for this set car during a call to getName , you must immediately call getName after retrieving it from the car object, for example:

 car.getName() // or car["getName"]() 

(Or via Function#call or Function#apply , which allows you to explicitly specify a value for this .)

What you do in your example is really like this:

 // Set f to the result of the assignment expression, // which is a reference to the getName function var f = (car.getName = car.getName); // Call it (separately) f(); 

... that's different. Functions called this way get this for the global object ( window , in browsers). (Other than strict mode, in strict mode this will be undefined .)

More (from my anemic blog):

Is there some kind of mechanism (using a variable or another) that monitors the non-use of the object function, so if such a situation occurs, will this mechanism prevent the assignment of this keyword as usual (as equal to the object)?

I'm not quite sure that I am following this question, but if you want to have a function that always has a predefined value of this , then yes, there are several ways to do this.

One of them is to use the new ES5 bind function:

 var name = "Jaguar"; var car = { name: "Ferrari" }; car.getName = function(){ return this.name; }.bind(car); alert((car.getName = car.getName)()); // "Ferrari" 

bind returns a function that always has this given by the argument you give it.

Another way is to use closure. And in fact, you can easily create a bind like function in ES3:

 function pseudoBind(func, thisArg) { return function() { return func.apply(thisArg, arguments); }; } 

This does not all bind , but has a part of this . Then you will have:

 var name = "Jaguar"; var car = { name: "Ferrari" }; car.getName = pseudoBind(function(){ return this.name; }, car); alert((car.getName = car.getName)()); // "Ferrari" 

More on closing (again from the blog):

In the future specification, we will get a declarative way of creating functions with a predefined value of this (the so-called arrow functions, because the syntax for them includes using => , and not the keyword function ).

+7
source

Aaah, this permission ... Let's take a gander.

 var toy = { log : function () { console.log(this); } }; toy.log() //logs the toy object 

It still seems that the permission of this static: wherever the method was defined, the value of this .

But! What to do if we do this:

 var sneakyBastard = toy.log; sneakyBastard(); //logs Window 

this bound to the object with which it called. In the case of toy.log you called log in the context of the toy object. But sneakyBastard does not have an established context, so you call window.sneakyBastard .

Now let’s take the goose (goose? Gander? No ...) in your expression:

 (car.getName = car.getName)() 

... and what does the assignment return? The assigned value, in this case, of the function, car.getName . We can break this expression into two:

 var returnedValue = (car.getName = car.getName); returnedValue(); 

... and from here it is obvious.

+5
source

Instead of calling getName from the context of the object, you call it from the context of the result of the return of the grouping operator (which in this case has no context).

In JavaScript, when there is no clear context, the default value is used. Default...

  • global object when it is in strict mode

  • undefined if not in strict mode

+2
source

You put your function call bracket ( () ) so that they call the result of the expression (car.getName = car.getName) (which is the value (function) assigned to car.getName )

+1
source

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


All Articles