返回
this的指向 & call apply bind的内部实现剖析
前端
2024-01-08 21:17:29
相信很多朋友对this的指向经常遇到,本文总结了this的几种主要场景的指向。并且对call apply bind这三种改变this指向的底层方法进行了实现。
this的指向
对于this,我们首先会碰到一个疑问:this指向什么 ?
我们先看一看场景:
-
看方法前面是否有点,如果没有 ,那么它的指向在严格模式下是undefined,非严格模式下指向的是window;如果方法前面有点,那么点前面是谁,this就指向谁。
-
普通函数的情况 :
let obj = {
name: "obj",
getName: function() {
return this.name;
}
};
let getName = obj.getName;
console.log(obj.getName()); // obj
console.log(getName()); // undefined
在上面的代码中,this的指向取决于函数的调用方式。obj.getName()中,this指向obj。而在getName()中,this指向undefined,因为普通函数作为参数被调用时,this指向全局对象window(非严格模式下)。
- 箭头函数的情况 :
箭头函数的this指向是由其所在的环境决定的。在上面的代码中,箭头函数getNameArrow()被定义在obj对象中,因此它的this指向obj对象:
let obj = {
name: "obj",
getNameArrow: () => {
return this.name;
}
};
console.log(obj.getNameArrow()); // obj
- 构造函数的情况 :
构造函数的this指向new创建的实例对象。在下面的代码中,this指向Person实例对象:
function Person(name) {
this.name = name;
}
let person = new Person("John");
console.log(person.name); // John
call apply bind的内部实现剖析
现在我们了解了this的指向,我们再来看看call apply bind这三个函数是如何改变this指向的。
这三个函数的实现原理是相似的,都是通过改变函数的执行上下文来改变this的指向。
其中,call函数的实现如下:
Function.prototype.call = function(context, ...args) {
// 将this指向context对象
context.fn = this;
// 将参数args传给函数fn
const result = context.fn(...args);
// 删除context.fn属性
delete context.fn;
// 返回函数fn的执行结果
return result;
};
apply函数的实现如下:
Function.prototype.apply = function(context, args) {
// 将this指向context对象
context.fn = this;
// 将参数args传给函数fn
const result = context.fn(...args);
// 删除context.fn属性
delete context.fn;
// 返回函数fn的执行结果
return result;
};
bind函数的实现如下:
Function.prototype.bind = function(context, ...args) {
// 创建一个新的函数fn
const fn = (...bindArgs) => {
// 将this指向context对象
this.fn = this;
// 将参数bindArgs和args传给函数fn
const result = this.fn(...args, ...bindArgs);
// 删除this.fn属性
delete this.fn;
// 返回函数fn的执行结果
return result;
};
// 返回新的函数fn
return fn;
};
从上面的代码中,我们可以看到,call apply bind这三个函数的实现原理都是相似的,都是通过改变函数的执行上下文来改变this的指向。
但是,这三个函数在使用上有一些区别:
- call函数的参数是context和args,其中context是this要指向的对象,args是传递给函数的参数。
- apply函数的参数是context和args,其中context是this要指向的对象,args是一个数组,里面包含了传递给函数的参数。
- bind函数的参数是context和args,其中context是this要指向的对象,args是传递给函数的参数。bind函数不会立即执行函数,而是返回一个新的函数,这个新的函数的this指向是context,并且它的参数是bind函数的参数args和新的参数。
希望这篇博客对您有所帮助。如果您有任何问题,请随时给我留言。