1、call
1)实现代码
call 方法是在Function的原型对象上的方法, 所以所有的函数都可调用。我们手写的方法也放在Function的原型对象上。
Function.prototype.myCall = function (context, ...args) {
// 创建一个变量保存需要修改的this指向的对象, 如果没有传入就让this指向 window
let newThis = context || window;
// 给这个对象添加一个 fun 方法,这里的 this 就是调用 myCall 的这个函数
newThis.fun = this;
// 执行这个对象的 fun 方法, 并将 myCall 中传入的后续参数传给它;将执行结果保存给变量 res
let res = newThis.fun(...args);
// 删除这个对象的 fun 方法 避免产生副作用
delete newThis.fun
// 将执行结果返回
return res
}
2)效果验证
let obj = {
name: "xiaoming",
age: 24,
sayHello: function (job, hobby) {
console.log(`我叫${this.name},今年${this.age}岁。我的工作是: ${job},我的爱好是: ${hobby}。`);
}
}
let obj1 = {
name: "lihua",
age: 30
}
obj.sayHello.myCall(obj1, '设计师', '画画'); // 我叫lihua,今年30岁。我的工作是: 设计师,我的爱好是: 画画。
2、apply
1)实现代码
apply 的实现基本和call相同, 区别在于接参方式不同
Function.prototype.myApply = function (context, args) {
// 创建一个变量保存需要修改的this指向的对象, 如果没有传入就让this指向 window
let newThis = context || window;
// 给这个对象添加一个 fun 方法,这里的 this 就是调用 myApply 的这个函数
newThis.fun = this;
// 执行这个对象的 fun 方法, 并将 myApply 中传入的第二个参数展开传给它;将执行结果保存给变量 res
let res = newThis.fun(...args);
// 删除这个对象的 fun 方法 避免产生副作用
delete newThis.fun
// 将执行结果返回
return res
}
2)效果验证
let obj = {
name: "xiaoming",
age: 24,
sayHello: function (job, hobby) {
console.log(`我叫${this.name},今年${this.age}岁。我的工作是: ${job},我的爱好是: ${hobby}。`);
}
}
let obj1 = {
name: "lihua",
age: 30
}
obj.sayHello.myApply(obj1, ['设计师', '画画']); // 我叫lihua,今年30岁。我的工作是: 设计师,我的爱好是: 画画。
3、bind
1)实现代码
bind的里面会返回一个修改了this指向的function,在调用这个function时会把bind中传入的参数和调用函数时的传入的参数拼接一起传入给它
Function.prototype.myBind = function (context, ...args) {
// 创建一个变量保存需要修改的this指向的对象, 如果没有传入就让this指向 window
let newThis = context || window;
// 给这个对象添加一个 fun 方法,这里的 this 就是调用 myBind 的这个函数
newThis.fun = this;
// 返回一个函数
return function (...someArgs) {
// 执行这个对象的 fun 方法, 并将 myBind 中传入的后续参数拼接调用时传入的参数一起传给它;将执行结果保存给变量 res
let res = newThis.fun(...args, ...someArgs);
// 删除这个对象的 fun 方法 避免产生副作用
delete newThis.fun
// 将执行结果返回
return res
}
}
2)效果验证
let obj = {
name: "xiaoming",
age: 24,
sayHello: function (job, hobby) {
console.log(`我叫${this.name},今年${this.age}岁。我的工作是: ${job},我的爱好是: ${hobby}。`);
}
}
let obj1 = {
name: "lihua",
age: 30
}
obj.sayHello.myBind(obj1, '设计师', '画画')(); // 我叫lihua,今年30岁。我的工作是: 设计师,我的爱好是: 画画。
obj.sayHello.myBind(obj1, '设计师')('画画'); // 我叫lihua,今年30岁。我的工作是: 设计师,我的爱好是: 画画。