还是有点东西的呦!
手动实现call
预备知识:如果一个函数作为一个对象的属性,那么通过对象的.运算符调用此函数,this就是此对象
Function.prototype.myCall = function(context){
if(typeof this !== 'function'){
throw new TypeError('Error');
}
context = context || window;
let args = [...arguments.slice(1)];
//这里的这个this就是使用call的那个函数。因为是写在函数的原型上的,所以当一个具体的函数调用这个方法的时候,this就指向这个函数本身。本质上是给传入的这个对象先添加一个属性fn,这个属性的值就是调用call的那个函数。
context.fn = this;
let result = context.fn(...args);
//在调用完毕之后将这个fn属性删除掉。
delete context.fn;
return result;
}
-----------------------------------测试---------------------------------------------------
let obj = {
name:'张三',
age:10
};
function getInfo(){
console.log(this.name);
console.log(this.age);
}
getInfo.call(obj);
手动实现apply
在实现了call之后,实现apply相对来说就简单了,无非是传入参数不同而已。
Function.prototype.apply = function(context){
if(typeof this !== 'function'){
throw new TypeError('Error');
}
context = context || window;
context.fn = this;
let result;
if(arguments[1]){
context.fn(...arguments[1]);
}else{
context.fn();
}
delete context.fn;
return result;
}
function test(){
console.log(this.name);
console.log(this.age);
}
let obj = {
name:'李四',
age:18
}
test.apply(obj);
实现bind
Fucntion.prototype.myBind = function(context){
if(typeof this !== 'function'){
throw new TypeError('Error');
}
const that = this;
const args = [...arguments].slice(1);
return function F(){
//这里的判断是为了处理绑定的函数被用于new操作来创建新的对象,此时的this是指向新new出来的对象。不再是调用bind的那个函数了。
if(this instanceof F){
return new that(...args,...arguments)
}else{
return that.apply(context,args.concat(...arguments))
}
}
}