I will often see various written bind tutorials on the Internet, I recommend to see one of my principles on hu Hu — handwritten bind and bind’s Polyfill — MDN. The following are the questions and thoughts I encountered in the process of implementing handwritten BIND. If you are still wondering how to implement a handwritten BIND, you can take a look at the two articles above.
Handwritten bind vs native bind
Let’s start with a typical handwritten bind example, which looks like this:
Function.prototype.bind2 = function (context) {
if (typeof this! = ="function") {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}
var self = this;
var args = Array.prototype.slice.call(arguments.1);
var fNOP = function () {};
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
}
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}
Copy the code
Let’s first run the code with native BIND
function Foo(a) {this.a = a}
Foo.prototype.sayHi = function( ) {}
let _Foo = Foo.bind(undefined.'a')
new _Foo()
Copy the code
And then using the handwritten version of the code, you run the same code
function Foo(a) {this.a = a}
Foo.prototype.sayHi = function( ) {}
let _Foo = Foo.bind2(undefined.'a')
new _Foo()
Copy the code
We can see that the handwritten version of Bind returns an extra __proto__ constructor than the native bind method. The reason for __proto__ is to prevent prototype chain tampering mentioned in many tutorials.
This is why many articles will tell you why the following code should be added.
var fNOP = function () {};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
Copy the code
This code uses an empty function equivalent to Object.create(fbound.prototype) as a transition. Specific can view the article given at the beginning of the article, the detailed description inside.
Bind in the specification
Speaking of which, the code is added to prevent prototype chain tampering. I just want to see how native bind handles this problem.
function Foo(a) {this.a = a}
Foo.prototype.sayHi = function( ) {}
let _Foo = Foo.bind(undefined.'a')
_Foo.prototype.sayHi = function( ) {console.log('sayHi method for tampered _Foo')}
(new _Foo().sayHi())
Copy the code
I found that by running the above code, the program was already reporting an error when it reached the statement that modified the prototype method for _Foo. _Foo has no prototype property! Since there is no prototype attribute, is there no need to deal with prototype chain tampering?
Later, I checked the specification, and in the NOTE, there was the following paragraph. It is explicitly stated that bind returns functions that do not have the prototype attribute, somewhat confirming the above conjecture.
Function objects created using Function.prototype.bind do not have a prototype property or the [[Code]], [[FormalParameters]], and [[Scope]] internal properties.
One thing to watch out for is this:
- Set the [[Prototype]] internal property of F to the standard built-in Function prototype object as specified in 15.3.3.1.
The prototype attribute of the bind Function object is the built-in function. prototype attribute
summary
The purpose of this article is to summarize the problems encountered in the process of implementing BIND and record the process of exploration. Through a series of handwritten native methods, we have exercised our further understanding of the principle. But also pay attention to verification, the actual operation several times, may get their own experience. Let me know if there are any more comparisons in the comments.