当调用call时,call方法中的this就是调用体(也就是调用call的函数)
此时只需要将this赋值给传进来的对象,作为对象的方法进行调用,这样这个方法的this便会指向目标对象。当传进来的对象为null的时候,直接赋值为window
参数问题,,利用自带的arguments解决
function person(a,b,c,d){
console.log(‘name is ‘+this.name)
console.log(a,b,c,d)
return {
a:11,
b:12
}
}
let jack = {
name:‘jack‘
}
// 重写函数的call方法
Function.prototype.newCall=function (obj){
// 当obj为null的时候指向window
obj = obj || window
// 获取除第一个以外的参数
let arg = []
for(let i = 1;i < arguments.length;i++){
arg.push(arguments[i])
}
// 此处的this是调用体,在这里是person函数
obj.b = this
// 使用obj调用函数,使得被调用的函数的值指向obj
// 保留函数原来的返回值
const result = obj.b(...arg)
delete obj.b
return result
}
// 调用试一下
let result = person.newCall(jack,‘father‘,‘mother‘,‘sister‘,‘brother‘)
console.log(result)
调用bind时会返回一个函数,掉用函数时会改变this指向,获取this值,调用apply改变this指向
Function.prototype.newBind=function(obj){
const arg1 = Array.prototype.slice.call(arguments,1)
const that = this
return function(){
const arg2 = Array.prototype.slice.call(arguments)
return that.apply(obj,arg1.concat(arg2))
}
}
比较麻烦的是这个new操作,会改变this指向
如下
function showName(a,b){
console.log(this.name)
console.log(a,b)
}
let obj = {
name:‘第一个‘
}
let result = showName.bind(obj,‘参数1‘,‘参数2‘)
result() // "第一个" "参数1" "参数2"
let typeResult = new result() //undefined "参数1" "参数2"
故而需要进行如下修改
首先返回的函数应该是一个具名函数,这样可以明确调用时的this指向并实现原型链的继承
在调用时,需要使用instanceof判定当前的this是不是与返回的函数相关联
Function.prototype.newBind=function(obj){
const arg1 = Array.prototype.slice.call(arguments,1)
const that = this
let back = function(){
const arg2 = Array.prototype.slice.call(arguments)
if(this instanceof back){
return that.apply(this,arg1.concat(arg2))
}
return that.apply(obj,arg1.concat(arg2))
}
// 返回的值的原型对象需要与调用它的函数原型进行关联
back.prototype = Object.create(this.prototype)
// 上述语句与此处异曲同工
// function o(){}
// o.prototype = this.prototype
// back.prototype = new o()
return back
}
原文:https://www.cnblogs.com/axu1997/p/14838962.html