1.介绍
1.1 什么是 this 指向?
在 JavaScript 中,this 是一个特殊的关键字,它可以在不同的代码上下文中指向不同的对象或者值,也就是说它是“动态的”,而不是一成不变的。
1.2 那为什么要改变 this 指向呢?
接下来我举一个简单的例子
var name="小红";
var obj={
name:"小明",
fn:function () {
console.log(this.name);
}
};
obj.fn(); //小明,this 指向了 obj
setTimeout(obj.fn,0); //小红,this 指向 window(我们想要的是小明)
原因:setTimeout内的函数是回调函数,即使设置时间为 0
表示的也是在当前任务完成后尽快执行,而不是立即执行
所以 setTimeout内的回调是在全局上下文执行的,并不是在 obj 对象中执行
2. this 的具体指向
在没有人为的干预情况下,大部分情况下“this”的值取决于调用的“对象”
例如:
作为普通函数调用的时候,这个时候相当于 "window"调用了该函数
即 this 指向了全局作用域(值为 undefined)
作为对象的方法调用的时候,这个时候相当于由对象调用了该方法
即 this 指向了该对象
特殊:构造函数创建对象(new)的时候,作用域和原型链都会赋值给新对象
即 this 指向了新对象
3.改变 this 的方法
3.1 call
语法:(this的指向,参数列表)
特点:
* 第二个参数传入的是参数列表(也就是说参数需要一个个给)
* 临时改变了 this 指向,也就是一次性的
例子:还是最开始的例子(最上面那个)
setTimeout(obj.fn.call(obj),0); //小明,成功修改了 this 指向
3.2 apply
语法:(this的指向,参数数组)
特点:
* 第二个参数传入的是参数数组(不需要一个个传参啦)
* 临时改变了 this 指向,也就是一次性的(跟 call 同理)
例子:修改一下例子
var name="小红";
var obj={
name:"小明",
fn:function (age,hobby) {
console.log(this.name,age,hobby);
}
};
setTimeout(obj.fn.apply(obj,["18","打篮球"]),0); //小明 18 打篮球
3.3 bind
语法:(this的指向,参数列表)
特点:
* 第二个参数传入的是可分多次传入的参数列表( call 必须一次性传入)
* 永久改变了 this 指向,并且返回一个函数(不会立即执行)
例子:
setTimeout(obj.fn.bind(obj,["18","打篮球"])(),0); //小明 18 打篮球
tip:在 setTimeout中会自动执行该回调函数,所以也是可以不用加"()"调用的,在这里是为了作出和 apply 的区别故加上
4.最后的小技巧
- 第一个参数如果是传 null 或者 undefined 的时候,则表示指向 window
- 函数需要多个参数时(用数组存放参数),用 apply 可将数组参数转换成参数列表
- 不使用方法修改 this 指向的时候,也可以在目标作用域外将 this 暂存起来(比如用 this 赋值给 that),然后在目标作用域中用 that 代替 this 的使用