一、this
this 是执行上下文中的一个属性,它指向最后一次调用这个方法的对象。在实际开发中,this 的指向可以通过四种调用模式来判断。
- 第一种是函数调用模式,当一个函数不是一个对象的属性时,直接作为函数来调用时,this 指向全局对象
- 第二种是方法调用模式,如果一个函数作为一个对象的方法来调用时,this 指向这个对象
- 第三种是构造器调用模式,如果一个函数用 new 调用时,函数执行前会新创建一个对象,this 指向这个新创建的对象
- 第四种是 apply 、call 和 bind 调用模式,这三个方法都可以显示的指定调用函数的 this 指向。
apply
方法接收两个参数:一个是 this 绑定的对象,一个是参数数组。
call
方法接收的参数,第一个是 this 绑定的对象,后面的其余参数是传入函数执行的参数
bind
方法通过传入一个对象,返回一个 this 绑定了传入对象的新函数。这个函数的 this 指向除了使用 new 时会被改变,其他情况下都不会改变
四种方式的优先级如下:
构造器调用模式 > apply、call、bind调用模式 > 方法调用模式 > 函数调用模式
二、手写apply、call、bind
1.apply
Function.prototype.myApply = function(context = window, args){
if(this === Function.prototype){
return undefined;
}
const fn = Symbol();
context[fn] = this;
let result;
if(Array.isArray(args){
result = context[fn](...args);
}else{
result = context[fn]();
}
delete context[fn];
return result;
}
2.call
Function.prototype.myCall = function(context = window, ...args){
if(this === Function.prototype){
return undefined;
}
const fn = Symbol();
context[fn] = this;
const result = context[fn](...args);
delete context[fn];
return result;
}
3.bind
Function.prototype.myBind = function(context, ...args1){
if(this === Function.prototype){
throw new TypeError('Error');
}
const _this = this;
return function F(...args2){
if(this instanceof F){
return new _this(...args1, ...args2);
}
return _this.apply(context, args1.concat(args2));
}
}