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.myBind=function(oThis, ...params){constthat=this;if(typeofthat!=='function'){thrownewError(`${this} is not callable`);}functionprototype(){};functionbind(...args){constisNew=thisinstanceofprototype;returnthat.apply(isNew ? this : oThis,[...params, ...args]);}// 引入中间函数,为了保证修改bind之后函数的原型对原函数原型不产生影响prototype.prototype=that.prototype;bind.prototype=newprototype();returnbind;}// 但是在规范中为了bind之后生成的函数的原型不影响到原函数的原型,所以所以直接将新生成的函数原型设置为undefined,为了更加贴合规范,我们使用下面这种方式进行模拟Function.prototype.myBind=function(oThis, ...params){constthat=this;if(typeofthat!=='function'){thrownewError(`${this} is not callable`);}functionbind(...args){constisNew=new.target===bind;if(isNew){returnnewthat(...params, ...args);}returnthat.apply(oThis,[...params, ...args]);}// 引入中间函数,为了修改bind之后函数的原型对原函数原型不产生影响bind.prototype=null;returnbind;}
从规范来看如何确定this
this就是构建上下文的时候重要的三个之一,但是this到底是怎么确定的?首先根据规范我们将ECMAscript中的类型分为两部分,一部分是语言类型:就是开发者直接可以操作的,另一种称之为规范类型:相当于 meta-values,是用来用算法描述 ECMAScript 语言结构和 ECMAScript 语言类型的。规范类型包括:Reference, List, Completion, Property Descriptor, Property Identifier, Lexical Environment, 和 Environment Record,这里面有个重要的属性为Reference,他和this的指向有着密切的联系。这个类型是为了解释诸如delete、typeof以及赋值等操作行为。Reference由三部分组成,分别是:
EnvironmentRecord
它的值只可能是语言类型或者EnvironmentRecord
那么函数调用的时候如何确定this的值:首先计算MemberExpression,将计算的结果赋值为ref,然后根据ref的情况来确定this的值,具体分了如下三种情况:
首先计算MemberExpression的结果赋值给ref,那么什么是MemberExpression?包含下面几种:
比如:
然后判断ref是不是一个Reference类型,按照上面提到规范进行处理。
解释下面的代码,说明当前this的指向:
但是函数中的this为什么执行undefined
在这个函数中,MemberExpression 是 foo,解析标识符,查看规范 10.3.1 Identifier Resolution,会返回一个 Reference 类型的值,类似如下这种:
但是IsPropertyReference(ref)返回结果是false,所以只能走第二种情况,this的值为IsPropertyReference(ref),这个函数始终返回的undefined,所以最后this的值就是undefined。
call、apply、bind、箭头函数、new 绑定this对比
this的绑定有三种方式,分别是:
函数在严格模式中会将this绑定为全局对象
首先call和apply的区别就是传入的参数不同,bind是通过call和apply来实现,所以将之称之为硬绑定
那么如何实现call和apply函数?
隐式绑定就是通过上面提到,判断this的过程
使用new的过程:
在了解到new的执行过程,我们可以手动实现一个new操作符,具体实现如下:
下面这两种情况是对上面出现的情况进行说明:
这四种方式存在优先级问题:
new 绑定>显式绑定>隐式绑定>默认绑定,new绑定和显式绑定判断如下:
这里面new和call/apply无法同时使用,所以只能通过显式绑定的变形-硬绑定来实现。
令人惊奇的是使用new竟然更改了硬绑定中的this,所以new 绑定this的优先级高于硬绑定。另一种比较有点事称之为软绑定。
如何绑定this
举例
The text was updated successfully, but these errors were encountered: