- Why do interviewers always ask you to implement a bind function?
- What does he want to know from Bind?
- What’s in a little bind?
Bind bind bind bind bind bind bind bind bind bind bind bind bind bind bind bind bind
👍 read useful students remember to point a praise to go again, your encouragement – MY great power to see what can be learned
- To realize the bind
- The new principle of
The narrative steps of this article
- Bind function
- Simulate the essentials of BIND
- Implementation approach
- New function special case (this& Parent prototype)
————- Manual dividing line ————-
The bind function
Returns a function to which this refers.
Simulate the essentials of BIND
- Change the direction of this
- Returns the function
Implementation approach
Create a function to return and change the pointer internally with call/apply, whose call/apply arguments are taken from arguments.
The implementation code is as follows:
Function.prototype.myBind = function () {
let exeFunc = this;
let beThis = arguments[0];
let args = [].slice.call(arguments ,1);
return function () { exeFunc.apply(beThis,args); }}Copy the code
Let’s put this to the test:
let other = {
name: 'other'
}
let obj = {
name: 'obj'.getName : function (age,height) {
console.log(this.name);
console.log('age' + age);
console.log('height' + height);
}
}
obj.getName.myBind(other, 14.200) ();Copy the code
The test results are normal. It prints other
Pretty easy, huh? But it’s often more than that. Then look at:
function Person() {
this.name = 'person';
this.getName = function (age, height) {
console.log(this.name);
console.log('age:' + age, 'height:'+ height); }}Copy the code
At this time:
let PersonMyBind = Person.myBind(window);
let per3 = new PersonMyBind();
per3.getName();
Copy the code
Do you print person?
Answer: Actually per3 is an empty object.
New function special case -this
So why did it go wrong. This brings us to new knowledge: if you don’t understand it, take a look at this article. This is a simulation of new code
function New (constructFunc) {
// Let obj = New(obj); => obj = res
var res = {};
if(constructFunc.prototype ! = =null) {
// Point the prototype of the instance to the prototype of the constructor
res.__proto__ = constructFunc.prototype;
}
// focus ret is the result of the constructor execution, change this of the constructor to execute res
var ret = constructFunc.apply(res, Array.prototype.slice.call(arguments.1));
// If the constructor returns a value, it returns it directly
if((typeof rest === "object" || typeof ret === "function") && ret ! = =null) {
return ret;
}
// Otherwise return the instance
return res;
}
Copy the code
Bind (name, getName) == == == == == == ==
var ret = constructFunc.apply(res, Array.prototype.slice.call(arguments.1));
Copy the code
Function () {exefunc.apply (beThis,args); exefunc.apply (beThis,args); }, let me make it clear.So when this line of code executes:
var ret = constructFunc.apply(res, Array.prototype.slice.call(arguments.1));
Copy the code
To see the difference between new Person and new PersonMyBind()How can we solve this problem once we know the cause of this phenomenon? It’s actually quite simple, if it’s new:
let resultFunc = function () {
exeFn.apply(this, args) // We pass in this object, which corresponds to the res in the new procedure
}
Copy the code
So the question is how to distinguish between new Person () and Person ()! The answer lies in the implementation of new. We can find this line in the new simulation above:
// Point the prototype of the instance to the prototype of the constructor
res.__proto__ = constructFunc.prototype;
Copy the code
That is to say executing
let resultFunc = function () {
// this__proto__ equals person.prototype
exeFn.apply(this, args)
}
Copy the code
This.__proto__ equals Person.prototype, so it’s ok to use this. Update our myBind
Function.prototype.myBind = function () {
if(typeof this! = ='function') {
throw new Error('Caller must be function type');
}
let exeFn = this; // this is the function to be executed
let currentThis = arguments[0]; // This to be specified
let args = [].slice.call(arguments.1); // The rest is passed as arguments
let resultFunc = function () {
// Distinguish between new calls and normal calls
exeFn.apply(this.__proto__=== resultFunc.prototype ? this : currentThis, args)
}
return resultFunc;
}
Copy the code
New function special case – parent prototype
This is not the end of the story, we also need to solve the case of the Person has a parent prototype, after knowing the above knowledge is very easy to solve this problem.
Function.prototype.myBind = function () {
if(typeof this! = ='function') {
throw new Error('Caller must be function type');
}
let exeFn = this; // this is the function to be executed
let currentThis = arguments[0]; // This to be specified
let args = [].slice.call(arguments.1); // The rest is passed as arguments
let resultFunc = function () {
// Distinguish between new calls and normal calls
exeFn.apply(this.__proto__=== resultFunc.prototype ? this : currentThis, args)
}
// Maintain the parent of the original function
if (this.prototype) {
resultFunc.prototype = this.prototype;
}
return resultFunc;
}
Copy the code
Finished work