📜 ⬆️ ⬇️

ECMA-262 standard (JavaScript) in pictures, part 2



In the first part of the article , the structures were considered execution context , lexical environment and Function objects. The second part is devoted to using this .

How this works


In the execution context, in addition to the VariableEnvironment, there is a field ThisBinding . When searching for ordinary variables, VariableEnvironment is used; when accessing through this , thisBinding . ThisBinding is set to the execution context , depending on how the function is called. If the function is called via the of () point, then ThisBinding will point to the object o . In all other cases, this binding will refer to the global object . In this case, the function may be the same.

For example, create a print function and an object o , and then add a function reference to the object. It turns out that the function can be called both print() and o.print() . ThisBinding will vary. If you copy the reference to o.print to the new variable print2 , then when you call print2 ThisBinding will point to the global object, despite the fact that the link was taken from the object.
')


Once again, if the call is "through the point", then ThisBinding indicates that up to the point. Otherwise, ThisBinding refers to the global object .

More details on how this is set when calling a function can be found in the following sections of the standard:


What happens when you call setTimeout


When using callbacks , the function reference is passed, but not the object. Therefore, when calling a callback, this will point to a global object .

In the case of setTimout, the first argument is a reference to the func function. After the specified delay, setTimeout calls it. The call is made without a dot, just like func() , so ThisBinding points to a global object .



The standard way to solve this problem is to save the object reference in the environment of the auxiliary function. Having a link to an object, you can use the Function.prototype.call function. When calling a function using call, you can explicitly specify a link that will be written in the ThisBinding context.

So when calling print.call(o) , a context will be created, in ThisBinding of which a reference to o will be written.

Such a function is usually called bind and can be implemented as follows.

 ... // bind  ,    f function bind(thisArg, f) { return function wrapper() { f.call(thisArg); } } //  bind   setTimeout(bind(o, o.print), 1); 

When the bind function is called, an environment is created and a Function object named wrapper . References to the object and the print function are stored in thisArg and f . In the scope of the Function object, a reference to the environment is placed. When you exit bind, the context is destroyed, but the environment remains because the wrapper refers to it.

enter image description here

When calling setTimeout via delay milliseconds, the wrapper function is called. When creating an environment , the scope field of the function being called is recorded in the outer field. In this case, outer will refer to the bind environment function. When f.call(thisArg) from the wrapper, both variables will be found in this environment . Then, when calling a call , a context will be created for print , where ThisBinding will point to o .

enter image description here

In JavaScript, there is a standard Function.prototype.bind method that allows you to remember not only this , but also the arguments of the function.

 //  setTimeout(bind(o, o.print), 1); //    bind setTimeout(o.print.bind(o), 1); 

In the next part, let's talk about prototype inheritance.

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


All Articles