this principle of js

This article is reproduced from Ruan Yifeng teacher's weblog --- this principle of JavaScript

First, the origin of the problem

Learn to JavaScript language, a sign is to understand the following two way, may have different results.


var obj = {
  foo: function () {}
};

var foo = obj.foo;

// 写法一
obj.foo()

// 写法二
foo()

The above code, though obj.foo, and foopoint to the same function, but the results may be different. Consider the following example.


var obj = {
  foo: function () { console.log(this.bar) },
  bar: 1
};

var foo = obj.foo;
var bar = 2;

obj.foo() // 1
foo() // 2

The reason for this difference lies in the functions that use thiskeywords. Many textbooks will tell you that thisrefers to the environment where the function is running. For obj.foo(), the foorunning objenvironment, so the thispoint obj; for foo()it, foorunning in the global environment, it thispoints to the global environment. Therefore, the results of the two are not the same.

This interpretation is right, but textbooks often do not tell you why this is so? In other words, the function of the operating environment in the end is how determined? For example, why obj.foo()is the objenvironmental performance, and once var foo = obj.foo, foo()it becomes the implementation of the global environment?

In this paper, to explain the principles of JavaScript handled this way. Understand this, you will completely understand the thisrole.

Second, the memory data structure

The reason JavaScript language has thisdesigned, with the memory inside data structures are related.


var obj = { foo:  5 };

The above object is a code assigned to the variable obj. JavaScript engine will be first in memory inside to produce an object { foo: 5 }, then the object memory address assignment to a variable obj.

In other words, the variable objis an address (reference). To read back obj.foo, the engine start objto get the memory address, and then read out the address from the original object, it returns the fooattributes.

Original object stored in a dictionary structure, each property name corresponds to a property description object. For example, an example of the above fooproperties, the following form is actually stored.


{
  foo: {
    [[value]]: 5
    [[writable]]: true
    [[enumerable]]: true
    [[configurable]]: true
  }
}

Note that the foovalue of the property is stored in the object attribute description valueattributes inside.

Third, function

Such a structure is very clear, that the value of the property in question might be a function.


var obj = { foo: function () {} };

In this case, the engine will function individually stored in memory, then the address is then assigned to the function fooattribute valueproperties.


{
  foo: {
    [[value]]: 函数的地址
    ...
  }
}

Since the function is a single value, it can be performed in a different environment (context).


var f = function () {};
var obj = { f: f };

// 单独执行
f()

// obj 环境执行
obj.f()

Fourth, the environment variable

JavaScript allowed inside the body of the function, refer to the current environment of other variables.


var f = function () {
  console.log(x);
};

In the above code, the variables used in the function body x. This variable is provided by the operating environment.

Now the question becomes, because the functions can be executed in a different operating environment, it is necessary to have a mechanism to get the current operating environment (context) inside the function body. So, thisthere have been, it is designed to function inside the body, refer to the function of the current operating environment.


var f = function () {
  console.log(this.x);
}

In the above code, the function body this.xrefers to the current operating environment x.


var f = function () {
  console.log(this.x);
}

var x = 1;
var obj = {
  f: f,
  x: 2,
};

// 单独执行
f() // 1

// obj 环境执行
obj.f() // 2

In the above code, the function fin the implementation of the global environment, this.xto the global environment x.

In objenvironmental performance, this.xpointing obj.x.

回到本文开头提出的问题,obj.foo()是通过obj找到foo,所以就是在obj环境执行。一旦var foo = obj.foo,变量foo就直接指向函数本身,所以foo()就变成在全局环境执行。

Guess you like

Origin blog.csdn.net/weixin_41615439/article/details/88697292