什么情况需要改变this指向
下例,正常情況 say方法输出martin 但是我们把 say 放在setTimeout 方法中,在定时器中是作为回调函数
来执行的,因此回到主栈执 行时是在全局执行上下文的环境中执行的,这时候this指向 window,所以输出Lucy 我们实际需要的是,this指向 obj对象,这时候就需要该改变 this指向了
javascript
var name = "lucy";
var obj = {
name: "martin",
say: function () {
console.log(this.name);
}
};
obj.say(); // martin this指向obj
setTimeout(obj.say,0); // lucy this指向window
// 改变this指向
setTimeout(obj.say.bind(obj),0); //martin this指向obj
共同点
- 都是显式改变this的方法
- 第一个参数都是this的指向
- 第一个参数是
null
或者undefined
时,默认指向window
(浏览器)
区别
- call 方法接收两个参数,第一个参数是this的值,第二个参数是传递给函数的参数,以
逗号分隔
,参数一次性传入。改变this指向后原函数会立即执行
,此方法只临时改变
this指向一次
。 - apply 方法也接收两个参数,第一个参数是this的值(为
null
或者undefined
时,默认指向window
(浏览器)),第二个参数一个数组或类数组对象
,改变this指向后原函数会立即执行
,此方法只临时改变
this指向一次
。 - bind 方法创建一个新的函数,当这个新函数被调用时,bind的第一个参数将作为它运行时的this,参数可分
多次传入
。改变this指向不会立即执行
,而是返回一个永久改变this指向的函数
。
scss
function fn(...args){
console.log(this,args);
}
let obj = { myname:"xxx" }
// apply
fn.apply(obj,[1,2]);
// call
fn.call(obj, 1,2);
// bind
const bindFn = fn.bind(obj);
// bind不会理解执行需要执行一次
bindFn(1,2) // this指向obj
fn() // this指向window
实现一个bind
- 修改this指向
- 动态传递参数
- 兼容new关键字
javascript
Function.prototype.myBind = function (context) {
// 判断调用对象是否为函数
if (typeof this !== "function") {
throw new TypeError("Error");
}
// 获取参数
const args = [...arguments].slice(1),
fn = this;
return function Fn() {
// 根据调用方式,传入不同绑定值
return fn.apply(this instanceof Fn ? new fn(...arguments) : context, args.concat(...arguments));
}
}