手动实现call
-
call的使用
let obj = { key:'obj value' } funciton getName(){ return this.name } console.log(getName.call(obj))
-
思考
1.如何在obj里面调用getName? 2.call方法是绑定在谁的身上?
-
解答
第一个问题,需要在obj内部添加一个getName方法var obj = { name:"obj name", getName:function(){ return this.name; } } console.log(obj.getName())
第二个问题,getName身上没有call,它会去Function.prototype上面去找
getName.prototype == Function.prototype
-
思路
1.Function.prototype 身上绑定 mycall 方法 2.调用getName.mycall时,给传进来的对象身上绑定getName方法 3.调用一次,然后删除,把调用结果返回
-
code
const obj = { key:'obj value' } function getValue (para1,para2) { return this.key + '-'+para1+'-'+para2 } Function.prototype.mycall = function (obj,para1,para2) { // console.log(this);// this 指向了调用它的对象 这里是[Function: getValue] let fnName = this.name // [Function: getValue] 函数原型上有name length 属性 obj[fnName] = this // 等同于 obj.getValue = ()=>{this.key} let result = obj[fnName](para1,para2) delete obj[fnName] //删除obj中的 getName方法 使得obj不受影响 return result } console.log(getValue.mycall(obj, 'from', 'mycall'));
手动实现apply
同call,只是传参方法变化
code
const obj = {
key:'obj value'
}
function getValue (para1,para2) {
return this.key + '-'+para1+'-'+para2
}
Function.prototype.myapply = function (obj,args) {
// console.log(this);// this 指向了调用它的对象 这里是[Function: getValue]
let fnName = this.name // [Function: getValue] 函数原型上有name length 属性
obj[fnName] = this // 等同于 obj.getValue = ()=>{this.key}
let result = obj[fnName](...args)
delete obj[fnName] //删除obj中的 getName方法 使得obj不受影响
return result
}
console.log(getValue.myapply(obj,['from','myapply']));
手动实现bind
- 借用call版本
const obj = {
key:'obj value'
}
function getValue (para1,para2) {
return this.key + '-'+para1+'-'+para2
}
Function.prototype.mybind=function(obj, para1, para2){
const _this = this
function inner (para1, para2) {
return _this.call(obj,para1, para2)
}
return inner
}
const bindFn = getValue.mybind(obj)
console.log(bindFn('from','mybind'));
- 原始版本
const obj = {
key:'obj value'
}
function getValue (para1,para2) {
return this.key + '-'+para1+'-'+para2
}
getValue.prototype.show = function () {
console.log('Dog');
}
Function.prototype.mybind = function (obj) {
const _this = this
let args = Array.prototype.slice.mycall(arguments, 1)
function inner () { //内部实现call方法
let innerArgs = Array.prototype.slice.mycall(arguments)
let finalArgs = args.concat(innerArgs)
let fnName = _this.name
obj[fnName] = _this
let result = obj[fnName](...finalArgs)
delete obj[fnName]
return result
}
/**
* 这里修正原型链(必须要的!)
* inner 的原型 指向了 Function
* 但是 fn 的原型不一定指向了 Function (比如fn是个构造函数,或者它原型上有自己的自定义方法)
* 所以 让inner 的原型 指向 fn的原型
*/
inner.prototype = Object.create(_this.prototype) //修正原型链
return inner //这里是一个闭包
}
const bindFn = getValue.mybind(obj)
console.log(bindFn('from','mybind'));
console.dir(bindFn.prototype.show());