Function.prototype.myCall = function (context) { let args = [...arguments].slice(1) context[this.name] = this let res = context[this.name](...args) delete context[this.name] return res }
(二) 手写实现 apply
1 2 3 4 5 6
Function.prototype.myApply = function (context, args) { context[this.name] = this let res = context[this.name](...args) delete context[this.name] return res }
(三) 手写实现 bind
1 2 3 4 5 6 7 8
Function.prototype.myBind = function (context) { let that = this let args = [...arguments].slice(1) returnfunction () { // 调用了前面手写的 apply return that.myApply(context, args.concat([...arguments])) } }
调用 bind 之后获得的绑定函数,如果将其当成构造函数和 new 搭配使用,那么原本调用 bind 时传入的第一个参数 context 将降低优先级,取而代之的是 new 操作符创建的那个新对象。而以上的实现过于简单,实现不了这个功能,以下是升级之后的版本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Function.prototype.myBind = function (context) { let that = this let args = [...arguments].slice(1) let fNOP = function() {} let fBound = function () { // 调用了前面手写的 apply return that.myApply(thisinstanceof fBound ? this : context, args.concat([...arguments])) } if (that.prototype) { fNOP.prototype = that.prototype } fBound.prototype = new fNOP() return fBound }