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 foo
point 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 this
keywords. Many textbooks will tell you that this
refers to the environment where the function is running. For obj.foo()
, the foo
running obj
environment, so the this
point obj
; for foo()
it, foo
running in the global environment, it this
points 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 obj
environmental 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 this
role.
Second, the memory data structure
The reason JavaScript language has this
designed, 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 obj
is an address (reference). To read back obj.foo
, the engine start obj
to get the memory address, and then read out the address from the original object, it returns the foo
attributes.
Original object stored in a dictionary structure, each property name corresponds to a property description object. For example, an example of the above foo
properties, the following form is actually stored.
{ foo: { [[value]]: 5 [[writable]]: true [[enumerable]]: true [[configurable]]: true } }
Note that the foo
value of the property is stored in the object attribute description value
attributes 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 foo
attribute value
properties.
{ 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, this
there 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.x
refers 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 f
in the implementation of the global environment, this.x
to the global environment x
.
In obj
environmental performance, this.x
pointing obj.x
.
回到本文开头提出的问题,obj.foo()
是通过obj
找到foo
,所以就是在obj
环境执行。一旦var foo = obj.foo
,变量foo
就直接指向函数本身,所以foo()
就变成在全局环境执行。