You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Function.prototype.bind = function(context){
let _this = this
let arg = Array.from(arguments).slice(1)
let bindFn = function(){
let arg2 = Array.from(arguments)
return _this.apply(this instanceof bindFn ? this : context, arg.concat(arg2))
}
// 这里不能直接写 bindFn.prototype = _this.prototype
// 如果这样写, 那 bindFn.prototype 和 原函数.prototype 会持有同一个对象的引用, 一旦我们修改了其中一个, 另一个也会改变
// 所以我们用一个函数中转
let bus = function(){}
bus.prototype = _this.prototype
bindFn.prototype = new bus() // 此时, new bindFn()实例的 __proto__ 指向这个new bus()实例, 这个new bus()实例的 __proto__ 又指向原函数.prototype, 原型链构建成功(*^▽^*)
return bindFn
}
5. 边界情况考虑
假如 bind 的不是一个函数呢?
拒绝。
if(typrof this !== "function"){
throw new Error("bind必须是函数调用")
return
}
最终代码:
Function.prototype.bind = function(context){
if(typrof this !== "function"){
throw new Error("bind必须是函数调用")
return
}
let _this = this
let arg = Array.from(arguments).slice(1)
let bindFn = function(){
let arg2 = Array.from(arguments)
return _this.apply(this instanceof bindFn ? this : context, arg.concat(arg2))
}
let bus = function(){}
bus.prototype = _this.prototype
bindFn.prototype = new bus()
return bindFn
}
实现bind
bind会创建一个新的函数返回, 这个函数被调用的时候, this指向bind的第一个参数, 之后的一系列参数都会传入作为函数的参数
1. 实现返回函数和指定this
2. 实现传参
bind的传参机制有点奇特, 它支持分两次传参, 也就是所需参数不用一次传完, 可以分两次传
实现思路: 分别用arguments接收, 然后拼接起来
以上就基本实现了bind, 但还差点东西:
3. 实现构造函数的判断
因为需要获取到实例的this, 所以这里就不用箭头函数了
4. 保持函数的原型
因为调用bind的函数可能是用作构造函数, 所以原函数上可能有些属性需要提供给实例访问
举个例子, 上面代码, 原有函数bind之前, 原有函数new出来的实例的原型指向原函数.prototype
但bind之后, 返回了bindFn, new出来的实例的原型指向bindFn.prototype, 丢失了原函数.prototype这一原型
5. 边界情况考虑
假如 bind 的不是一个函数呢?
拒绝。
最终代码:
参考: mqyqingfeng/Blog#12
The text was updated successfully, but these errors were encountered: