Created
April 3, 2019 18:02
-
-
Save ositowang/e212dbec409cc28db4e2d5fc22db09b4 to your computer and use it in GitHub Desktop.
a more comprehensive bind() that covers prototype chain and constructor function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Here comes the hardest parts. Have you considered if the function you are | |
* going to bind is a constructor function.In this scenario, the this value you | |
* bind should get ignored. | |
* | |
* @param {*} context | |
*/ | |
Function.prototype.bindUltimate = function(context) { | |
if (typeof this !== 'function') { | |
throw new Error('bind is only invoked on functions'); | |
} | |
let fn = this; | |
let args = [...arguments].slice(1); | |
let resultFn = function() { | |
let bindArgs = [...args]; | |
/** | |
* Here is tricky part: | |
* 1. if the fn is an constructor,this points to the instance, fn | |
* points to the function to be bound.However, we explicitly set the | |
* prototype of resultFn.prototype to the fn.prototype. Therefore, it would | |
* be true and the this is set to the instance. | |
* 2. if fn is not an constructor function. this points to the global | |
* object, fn points to the function to be bound. So the this set to the | |
* context passed in | |
*/ | |
fn.apply(this instanceof fn ? this : context, args.concat(bindArgs)); | |
}; | |
//dealing with the prototype issues, we uses a bus function to link to the chain | |
function bus() {} | |
bus.prototype = this.prototype; | |
resultFn.prototype = new bus(); | |
return resultFn; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment