call 方法内部实现
- 将这个函数设为指定对象的属性
- 传参后执行这个对象的方法
- 删除这个函数
- 返回对象的函数执行结果
模拟实现
Function.prototype.call2 = function(opp) {
opp.fn = this;
let args = [...arguments].slice(1);
let result = opp.fn(...args);
delete opp.fn;
return result;
}
apply 方法内部实现
思路类似手写call函数的思路如下,
不同:传参时只是第二个参数有,且为数组;不像call,除了第一个参数都是需要的参数
1.将这个函数设为指定对象的属性
2.传参后执行这个对象的方法
- 删除这个函数
4.返回对象的函数执行结果
模拟实现
Function.prototype.apply2 = function(opp) {
opp.fn = this;
let result;
if(auguments[1]) { //判断是否有第二个参数,即是否有传入调用函数的参数
result = opp.fn(…arguments[1])
} else {
result = opp.fn()
}
delete opp.fn;
return result;
}
bind 方法内部实现
- 返回一个函数,绑定this,传递预置参数
- bind返回的函数可以作为构造函数使用
需注意:通过new实例化后 this 指向的是创建出的新对象,还注意对原型链的影响
模拟实现
Funcrion.prototype.bind2 = function(opp) {
let fn = this;
let args = [...arguments].slice(1);
let resFn = function() {
fn.apply(this.instanceof fn ? this : opp, args.concat([...arguments]) )
// 检测 New: 如果当前函数的this指向的是构造函数中的this 则判定为new 操作
}
//为了完成 new操作, 还需要进行原型链接
// 这里创建了一个空函数来做中间人,承接原函数(此时为构造函数了)的原型 给 返回的绑定函数(resFn))
function Tmp() {}
Tmp.prototype = fn.prototype;
resFn.prototype = new Tmp(); // 修改返回函数的prototype为 绑定函数的prototype,这样的话通过new创建的实例就可以继承这个绑定函数(此为构造函数)中的属性;【原型链式继承】
//但是直接赋值的话当修改返回函数的prototype时绑定函数的prototype也不会被影响,所以创建了一个中间函数
return resFn;
}