this
foreword
When I read the scriptures, I found that my pointing to this was still a little vague. After reading a lot of this related articles, I plan to write an article to sort out this related knowledge , and use some common interview questions to strengthen my understanding for review and consolidation.
If you think the article is ambiguous, please point it out to avoid misleading more people! !
text
this
In the JavaScript language, everything is an object, and the runtime environment is also an object. Functions all run in an object, and this is the object (environment) where the function runs .
Why does this appear? Because functions can be executed in different operating environments, the appearance of this is to obtain (function) the current operating environment inside the function .
However, JavaScript supports dynamic switching of the runtime environment , which means that the pointing of this is dynamic, and there is no way to determine which object it points to in advance. This requires us to pay extra attention to the running environment of the function.
Let's take an example first ( from the article of Ruan Yifeng's predecessors ), although they are all executing foo. But the execution environment is not the same.
- For
obj.foo()
example, foo runs in the obj environment, so this points to obj; - For
foo()
example, foo runs in the global environment, so this points to the global environment.
var obj = {
foo: function () {
console.log(this.bar) },
bar: 1
};
var foo = obj.foo;
var bar = 2;
obj.foo() // 1
foo() // 2
If you want to understand this problem more deeply, you must understand the data structure of memory. The following picture is from Ruan Yifeng's this principle
var obj = {
foo: function () {
} };
For the code above, the variable obj is an address. If you want to read obj.foo, you must first get the memory address from obj, then read the original object from this address, and return its foo property.
The original object is stored in a dictionary structure, and each attribute name corresponds to an attribute description object. The value of the foo property is stored in the value property of the property description object. The function is stored separately in memory, and then the address of the function is assigned to the value property of the foo property.
So, a function is a single value , so it can be executed in a different environment (context), and JavaScript allows to reference other variables of the current environment inside the function body.
Use environment
global environment
When 全局环境
using this, it refers to the top-level object window
. Whether it is inside a function or not, as long as it is running in the global environment, this refers to the top-level object window.
console.log(this === window); // true
function f() {
console.log(this === window); //true
}
f() // true
If strict mode is used "use strict";
, it isundefined
function f(){
"use strict";
console.log(this);
}
f() //undefined
Constructor
构造函数
This in , refers to the instance object.
var Obj = function (p) {
this.p = p;
console.log(this);
};
var o = new Obj('Hello World!');
console.log(o.p); // "Hello World!"
object
If an object's method contains this, this points to the object where the method was run. Assigning this method to another object will change the pointer of this. Such as the following example
var a = 20;
var obj = {
a: 10,
getA: function () {
return this.a;
}
}
console.log(obj.getA()); //10
var test = obj.getA;
console.log(test()); //20 独立调用test
Notice! ! ! The following usage will change the pointing of this . obj.foo is a value. When this value is actually called, the runtime environment is no longer obj, but the global environment, so this no longer points to obj.
var obj ={
foo: function () {
console.log(this);
}
};
(obj.foo = obj.foo)() // window
In addition, if the method where this is located is not in the first layer of the object, then this only points to the object of the current layer, and will not inherit the upper layer . As follows, a.b.m
the method is in the second layer of the a object, the this inside the method does not point to a, but points to ab
var a = {
p: 'Hello',
b: {
m: function() {
console.log(this.p);
}
}
};
a.b.m() // undefined
show binding
The article can be viewed:
Related interview questions
1
var m = 10;
function fn() {
return this.m + 1;
}
var obj = {
m: 5,
test1: function() {
return fn();
}
};
obj.test2 = fn;
console.log(obj.test1(), fn(), obj.test2()) // 11 11 6
If you turn var into let the answer is: NaN NaN 6
. The first two this.m
are undefined, because the m declared with let belongs to the scope of the script, not windows
the property on the body.
2
var obj = {
a: 10,
b: this.a + 10, //这里的this指向window(全局),a为undefined ==> undefined + 20 = NaN
fn: function () {
return this.a;
}
}
console.log(obj.b); //NaN
console.log(obj.fn()); //10
3
var a = 5;
function fn1(){
var a = 6;
console.log(a); //6
console.log(this.a); //5
}
function fn2(fn) {
var a = 7;
fn();
}
var obj = {
a: 8,
getA: fn1
}
fn2(obj.getA);
4
// 构造函数
function Person(name, age) {
this.name = name;
this.age = age;
console.log(this); //Person实例对象
}
Person(); //window
Person.prototype.getName = function () {
console.log(this); //Person实例对象
};
var p1 = new Person("test", 18);
p1.getName();
5
var obj = {
foo: "test",
fn: function(){
var mine = this;
console.log(this.foo); //test
console.log(mine.foo); //test
(function(){
console.log(this); // window
console.log(this.foo); //undefined
console.log(mine.foo); //test
})();
}
};
obj.fn();
6
function test(arg) {
this.x = arg;
return this;
}
var x = test(5); //此时 x = window, y = undefined
var y = test(6); //此时 x = 6, y = window
console.log(x.x); //undefined, 6.x是undefined
console.log(y.x); //6 实际上是window.x 也就是6
7
var obj = {
data: [1,2,3,4,5],
data2: [1,2,3,4,5],
fn: function () {
console.log("--test--");
console.log(this); //Object
return this.data.map(function (item) {
console.log(this); //window
return item * 2;
});
},
fn2: function () {
console.log("---test2---");
console.log(this); //Object
return this.data2.map(item=>{
console.log(this); //Object
return item * 2;
});
}
};
obj.fn();
obj.fn2();
If you find this article useful, please like and subscribe! !