原理:改变函数的
this指向
class Par{
constructor(name,age){
this.name = name
this.age = age
}
say(sex='',like=''){
return (`姓名---${this.name},年龄---${this.age},性别---${sex},爱好---${like}`)
}
}
let son = new Par('TTT',18)
son.say()// 姓名---TTT,年龄---18
let obj = {name:'ttt',age:10}
son.say.call(obj,'男','美女')//姓名---ttt,年龄---10,性别---男,爱好---美女,直接执行函数
son.say.apply(obj,['男','美女'])// 姓名---ttt,年龄---10,性别---男,爱好---美女,直接执行函数
son.say.bind(obj,['男','美女'])()// 姓名---ttt,年龄---10,性别---男,爱好---美女,返回的是个函数,还需要调用
son.say的this指向为实例 son (谁调用的say,this就是指向谁),通过调用Function原型的call,改变了this指向为 obj
手写一个粗略版call(顺便把apply也说一下)
call 内部是怎么改变这个this指向的呢,上面说到根据谁调用这个函数,这个函数内部的this就是指向谁,那么我们是不是把 son.say.call(obj) 里面的 son.say, 改成 obj.say 的话,this 不就是指向obj 了吗?
Function.prototype.newCall = function(content=window){
//son.say.call2(obj2)
//我们需要把this改成obj2
//this = say,content = obj2,我们在obj添加一个属性,指向say函数
content.fn = this
//call2的第二个参数----传给say函数的参数
//apply的话,就判断 arguments[1] 存在的话,直接结构 ...arguments[1] ,因为它本身就是一个数组
let args = [...arguments].slice(1);
//执行这个say函数,此时,say里面的this指向就变成了content
let result = content.fn(...args)
// 删除临时属性
Reflect.deleteProperty(content,'fn')
//delete content.fn delete在严格模式下会报错
//如果 say 函数需要一个返回值,这里是需要 return 才能拿到执行函数后的返回的
//例:son.say.call2(obj2) 可以不需要return
//let conSon = son.say.call2(obj2) 如果要获取 conSon 则需要 return 回执行函数的返回值
return result
}
class Par{
constructor(name,age){
this.name = name
this.age = age
}
say(sex='',like=''){
return (`姓名---${this.name},年龄---${this.age},性别---${sex},爱好---${like}`)
}
}
let son = new Par('TTT',18)
son.say()// 姓名---TTT,年龄---18
let obj = {name:'ttt',age:10}
son.say.call(obj)// 姓名---ttt,年龄---10,性别---'',爱好---''
son.say.newCall(obj)// 姓名---ttt,年龄---10,性别---'',爱好---''
手写一个粗略版bind
bind 返回的是一个函数,所以在函数内部的
this和args会改变,需要在函数外部定义
Function.prototype.newBind = function (content = window) {
let that = this
let args = arguments[1]?...arguments[1]:'';
return function () {
//this = say,content = obj,我们在obj添加一个属性,指向say函数
content.fn = that
//执行这个say函数,此时,say里面的this指向就变成了content
let result = content.fn(args)
// 删除临时属性
Reflect.deleteProperty(content, 'fn')
//如果 say 函数需要一个返回值,这里是需要 return 才能拿到执行函数后的返回的
//例:son.say.newCall(obj) 可以不需要return
//let conSon = son.say.newCall(obj1) 如果要获取 conSon 则需要 return 回执行函数的返回值
return result
}
}
以上!!!