You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Function.prototype.bind2=function(context){if(typeofthis!=="function"){thrownewError("Function.prototype.bind - what is trying to be bound is not callable");}varself=this;varargs=Array.prototype.slice.call(arguments,1);varfNOP=function(){};varfBound=function(){varbindArgs=Array.prototype.slice.call(arguments);returnself.apply(thisinstanceoffNOP ? this : context,args.concat(bindArgs));}fNOP.prototype=this.prototype;fBound.prototype=newfNOP();returnfBound;}
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的教程,推荐看一篇就够了 冴羽大佬——手写bind以及bind的Polyfill——MDN。下面是我在自己实现手写bind的过程中遇到的问题与思考。如果对于如何实现一个手写bind还有疑惑的话,那么可以先看看上面两篇文章。
手写bind vs 原生bind
我们先使用一个典型的手写bind的例子,代码如下:
我们首先用原生bind运行一下代码
然后使用手写版代码,运行同样的代码
我们可以看到相比原生bind方法,手写版的bind方法返回的构造函数,构造出来的新对象会比原生的多一层
__proto__
。而这个__proto__
产生的原因就是在很多教程中提到的防止原型链篡改。这也就是为什么很多的文章会告诉你,为什么要添加下面的代码。
这段代码中,使用了一个空函数作为中转,相当于
Object.create(fBound.prototype)
。具体可以查看文章开头给出的文章,里面的详细的说明。规范中的bind
既然说道,加上面的代码是为了防止原型链篡改。我就想看看原生的bind如何处理这个问题的呢?
我发现在运行上面的代码,程序执行到修改
_Foo
的原型方法的语句时,就已经报错了。提示表明_Foo
没有prototype
属性!既然没有prototype
属性,那么是不是也就不用处理原型链篡改的问题了呢?之后,我查了一下规范, 在NOTE中,有下面一段话。明确指出了bind返回的函数是没有
prototype
属性,这也多少印证了上面的猜想。其中需要注意的有一点是这条:
我自己理解的意思是是bind出来的函数对象的prototype属性是内建的
Function.prototype
属性, 这里应该是说明了为什么原生的bind不会多一层__proto__
属性小结
写这篇的目的是总结下自己在实现bind过程中遇到的问题,记录探究的过程。通过一系列手写原生方法,锻炼了我们对于原理的进一步认识。但是也要注意验证,实际去操作几次,可能得出自己的经验。如果有更多的两者对比的发现,可以在评论里告诉我,欢迎各位大佬斧正。
The text was updated successfully, but these errors were encountered: