THIS 的指向

JavaScript的 this 指向调用该函数的对象

JavaScript中所有的函数都有属性,就如对象有属性一样。函数执行阶段(也即执行上下文的执行阶段)会获取this属性的值,此时this就是一个变量,储存着调用该函数的对象的值。
eg.

1
2
3
4
5
6
var a = "coffe";

function func() {
console.log(this.a);
}
func(); //>> coffe

上面代码中,func的调用者未通过点操作符. 指明,那它的调用者就是默认的全局对象window,func函数作为window的一个方法,其体内的this.a就是明确指代window中属性a

this的指向规则

1 默认指向

独立函数调用(无法应用其他指向规则时),this指向全局对象window
在setInterval和setTimeout中传入函数时,函数中的this会指向window对象

2 隐式指向

一、 函数体内this的指向, 由调用位置的调用者决定。
若调用者调用的函数,为对象A的方法,那么该函数在被调用时,其内部的this指向对象A。
tips: 函数被当做某个对象的方法而调用 即 隐式指向。
二、 this指向最终调用函数的对象。即指向最靠近的被调用函数的对象,而不是离得远的。

隐式丢失

隐式丢失最容易在赋值时发生;隐式丢失发生时,调用这个函数会应用默认指向规则
eg.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function func() {

console.log( this.a );

}

var obj = {

a: "coffe1891",
func: func

};

var bar = obj.func; // 间接引用。此时 bar 和obj.func 其实都指向内存中的函数func本身。
var a = "oops, global"; // a 是全局对象window的属性,也是全局变量
bar(); //>> oops, global

// 虽然 bar 是 obj.func 的一个引用,但是实际上,它引用的是func函数本身,
// 因此此时的 bar() 其实是一个不带任何定语的独立函数调用,应用【默认指向】规则,
// 因此函数体内的this指向window,this.a指向window的属性a(全局变量a)

function func() {
console.log(this.a);
}
var a = 2;
var o = { a: 3, func: func };
var p = { a: 4 };
o.func(); //>> 3
(p.func = o.func)(); //>> 2
// 赋值表达式 p.func=o.func 的返回值是目标函数的引用,也就是 func 函数的引用
// 因此调用位置是 func() 而不是 p.func() 或者 o.func()

3 显示指向

JavaScript内置对象Function的三个原型方法call()、apply()和bind(),它们的第一个参数是一个对象,它们会把这个对象绑定到this,接着在调用函数时让this指向这个对象
另外,使用bind可以修正SetTimeout和SetInterval的this指向。

4 “new”操作符指向

在JavaScript 中,构造函数只是一些使用new操作符时被调用的函数。它们并不会属于某个类,也不会实例化一个类。只是被new操作符调用的普通函数而已
使用new 来调用函数,会自动执行下面的操作:
构造一个全新的对象;
将构造函数的作用域赋给新对象(因此this就指向了这个新对象);
执行构造函数中的代码(为这个新对象添加属性、方法等);
如果函数没有返回其他对象,那么返回这个新对象。

例外情况

1 被忽略的this

null 或者undefined 作为this指向的对象传入call、apply或者bind时,实际应用默认指向规则。

function func() {
console.log(this.a);
}

var a = 2;
func.call(null); //>> 2 //this指向了window

2 隐式指向中的隐式丢失

赋值时最容易发生。隐式丢失后,自动应用默认指向规则

3 箭头函数

箭头函数不遵守this的四种指向规则,而是根据函数定义时的作用域来决定 this 的指向。
即 你定义这个箭头函数的时候,该箭头函数在哪个函数里,那么箭头函数体内的this就是它父函数的this。
eg.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function func() {
// 返回一个箭头函数
return a => {
//this 继承自 func()
console.log(this.a);
};
}
var obj1 = {
a: 2
};
var obj2 = {
a: 3
};

var bar = func.call(obj1);
bar.call(obj2); //>> 2 不是 3 !

// func() 内部创建的箭头函数会捕获调用时 func() 的 this。
// 由于 func() 的 this 绑定到 obj1, bar(引用箭头函数)的 this 也会绑定到 obj1,
// this一旦被确定,就不可更改,所以箭头函数的绑定无法被修改。(new 也不行!)
查看评论