apply
手写的思路: 在Function上添加方法, 这样所有函数都拥有该方法可直接调用
接收需要绑定的对象和函数调用时传入的参数并判断对象是否存在
创建一个唯一值, 让对象的唯一值属性=this, 也就是调用该方法的函数
执行对象中的唯一值属性, 即使用对象调用函数, 完成了this绑定
删除对象的唯一值属性
/*
apply
context: 传入的要绑定this到的对象
args: 原函数执行时传入的参数, 为一个数组
*/
Function.prototype.myApply = function(context, args) {
// 传入的对象如果没有就绑定给window, 有的话也需要使用Object包装一下, 比如number包装为Number对象
context = Object(context) || window
// 唯一值, 避免覆盖context的属性
let unique = Symbol()
// 添加对象的属性给this, this就是调用该方法的函数, 即把函数作为了传入对象的方法, 实现了this绑定
context[unique] = this
// 执行函数, 并获取执行结果
let result = context[unique](...args)
// 删除对象的该属性
delete context[unique]
return result
}
call
和apply基本一致, 就是参数传递的方式不一样, 一个是数组, 一个是rest参数
Function.prototype.myCall = function(context, ...args) {
// 传入的对象如果没有就绑定给window, 有的话也需要使用Object包装一下, 比如number包装为Number对象
context = Object(context) || window
// 唯一值, 避免覆盖context的属性
let unique = Symbol()
// 添加对象的属性给this, this就是调用该方法的函数, 即把函数作为了传入对象的方法, 实现了this绑定
context[unique] = this
// 执行函数, 并获取执行结果
let result = context[unique](...args)
// 删除对象的该属性
delete context[unique]
return result
}
bind
就是将绑定this并执行的语句封装到一个函数里并返回
Function.prototype.myBind = function(context, ...args) {
context = Object(context) || window // 同上
// 待返回的函数, 该函数执行时, 执行并返回里面绑定this并调用的语句
let bindFun = (...newArgs) => {
return this.call(context, ...args, ...newArgs)
}
// 如果函数没有prototype, 如箭头函数
if(!bindFun.prototype) {
bindFun.prototype = this.prototype
}
return bindFun
}