当前位置: 首页 > Web前端 > JavaScript

面试官:你会用JavaScript手写一个bind函数吗?_2

时间:2023-03-27 00:03:48 JavaScript

我经常在网上看到各种手写的bind教程。下面是我在实现手写bind过程中遇到的问题和思考。如果你对如何实现手写bind还有疑惑,可以先看看上面两篇文章。手写bindvsnativebind我们先用一个典型的手写bind例子,代码如下:.prototype.bind-试图绑定的是不可调用的");}变种自己=这个;varargs=Array.prototype.slice.call(arguments,1);varfNOP=函数(){};varfBound=function(){varbindArgs=Array.prototype.slice.call(参数);returnself.apply(thisinstanceoffNOP?this:context,args.concat(bindArgs));}fNOP.prototype=this.prototype;fBound.prototype=newfNOP();returnfBound;}让我们首先使用原生绑定函数Foo(a){this.a=a}Foo.prototype.sayHi=function(){}let_Foo=Foo.bind(undefined,'a')new_Foo运行代码()然后使用手写版本,运行同样的代码()我们可以看到,与原来的bind方法相比,手写版bind方法返回的构造函数会构造一个比原来多一层__proto__的新对象。之所以设置这个__proto__,是为了防止很多教程中提到的原型链被篡改。这就是为什么很多文章会告诉你为什么要添加下面的代码。varfNOP=函数(){};fNOP.prototype=this.prototype;fBound.prototype=newfNOP();这段代码中使用了一个空函数作为传递,相当于Object.create(fBound.prototype)。具体可以参考文章开头给出的文章进行详细说明。参考:前端手写面试题详解由于规范中的bind说了,所以添加上面的代码是为了防止原型链被篡改。我就是想看看nativebind是怎么处理这个问题的?functionFoo(a){this.a=a}Foo.prototype.sayHi=function(){}let_Foo=Foo.bind(undefined,'a')_Foo.prototype.sayHi=function(){console.log('Tamped_Foo'ssayHimethod')}(new_Foo().sayHi())运行上面的代码发现,当程序执行修改_Foo的原型方法的语句时,一直报错。提示显示_Foo没有原型属性!既然没有原型属性,那么就不用处理原型链被篡改的问题了吗?之后,我检查了规格。在注释中,有以下段落。明确指出bind返回的函数没有prototype属性,多少印证了上面的猜想。使用Function.prototype.bind创建的函数对象没有原型属性或[[Code]]、[[FormalParameters]]和[[Scope]]内部属性。需要注意的一件事是:将F的[[Prototype]]内部属性设置为15.3.3.1中指定的标准内置Function原型对象。我的理解是bind产生的函数对象的prototype属性是内置的Function.prototype属性,这里应该解释一下为什么nativebind没有多一层__proto__属性总结写这篇文章的目的是总结一下自己在实现bind的过程中遇到的问题,记录一下摸索的过程。通过一系列的手写原生方法,锻炼了我们对原理的进一步理解。但是也要注意验证,实际做几次说不定会有自己的体会。如果大家发现两者更多的对比,可以在评论中告诉我,欢迎指正。