建设网站的安全性介绍,网络规划设计师报名,福田公司企业文化,电子商务网站建设产品经常会看到网上各种手写bind的教程#xff0c;下面是我在自己实现手写bind的过程中遇到的问题与思考。如果对于如何实现一个手写bind还有疑惑的话#xff0c;那么可以先看看上面两篇文章。
手写bind vs 原生bind
我们先使用一个典型的手写bind的例子#xff0c;代码如下下面是我在自己实现手写bind的过程中遇到的问题与思考。如果对于如何实现一个手写bind还有疑惑的话那么可以先看看上面两篇文章。
手写bind vs 原生bind
我们先使用一个典型的手写bind的例子代码如下
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;
}我们首先用原生bind运行一下代码
function Foo(a) {this.a a}
Foo.prototype.sayHi function( ) {}
let _Foo Foo.bind(undefined, a)
new _Foo() 然后使用手写版代码运行同样的代码
function Foo(a) {this.a a}
Foo.prototype.sayHi function( ) {}
let _Foo Foo.bind2(undefined, a)
new _Foo() 我们可以看到相比原生bind方法手写版的bind方法返回的构造函数构造出来的新对象会比原生的多一层__proto__。而这个__proto__产生的原因就是在很多教程中提到的防止原型链篡改。
这也就是为什么很多的文章会告诉你为什么要添加下面的代码。
var fNOP function () {};
fNOP.prototype this.prototype;
fBound.prototype new fNOP();这段代码中使用了一个空函数作为中转相当于Object.create(fBound.prototype)。具体可以查看文章开头给出的文章里面的详细的说明。
规范中的bind
既然说道加上面的代码是为了防止原型链篡改。我就想看看原生的bind如何处理这个问题的呢参考 前端进阶面试题详细解答
function Foo(a) {this.a a}
Foo.prototype.sayHi function( ) {}
let _Foo Foo.bind(undefined, a)
_Foo.prototype.sayHi function( ) {console.log(篡改的_Foo的sayHi方法)}
(new _Foo().sayHi())我发现在运行上面的代码程序执行到修改_Foo的原型方法的语句时就已经报错了。提示表明_Foo没有prototype属性既然没有prototype属性那么是不是也就不用处理原型链篡改的问题了呢
之后我查了一下规范, 在NOTE中有下面一段话。明确指出了bind返回的函数是没有prototype属性这也多少印证了上面的猜想。 Function objects created using Function.prototype.bind do not have a prototype property or the [[Code]], [[FormalParameters]], and [[Scope]] internal properties. 其中需要注意的有一点是这条 Set the [[Prototype]] internal property of F to the standard built-in Function prototype object as specified in 15.3.3.1. 我自己理解的意思是是bind出来的函数对象的prototype属性是内建的Function.prototype属性, 这里应该是说明了为什么原生的bind不会多一层__proto__属性
小结
写这篇的目的是总结下自己在实现bind过程中遇到的问题记录探究的过程。通过一系列手写原生方法锻炼了我们对于原理的进一步认识。但是也要注意验证实际去操作几次可能得出自己的经验。如果有更多的两者对比的发现可以在评论里告诉我欢迎各位大佬斧正。