JS手寫bind之處理new的情況詳解_第1頁
JS手寫bind之處理new的情況詳解_第2頁
JS手寫bind之處理new的情況詳解_第3頁
JS手寫bind之處理new的情況詳解_第4頁
JS手寫bind之處理new的情況詳解_第5頁
已閱讀5頁,還剩1頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

第JS手寫bind之處理new的情況詳解目錄new判斷函數(shù)是否通過new被調(diào)用new和bind實(shí)現(xiàn)完整的bind結(jié)尾大家好,我是前端西瓜哥。

之前寫了一篇關(guān)于JS中bind方法的實(shí)現(xiàn)的文章,并給出了實(shí)現(xiàn):

Ftotype.myBind=function(thisArg,...prefixArgs){

constfn=this;

returnfunction(...args){

returnfn.call(thisArg,...prefixArgs,...args);

但沒有處理通過new創(chuàng)建實(shí)例的情況。

因為很少會遇到給bind返回的函數(shù)做new操作的場景,所以我沒去考慮這種特殊情況。

但面試中還是會涉及到的,我們還是實(shí)現(xiàn)一下兼容new操作的bind寫法,順便學(xué)習(xí)一下new操作符。

因為存在一定上下文,在閱讀本文前,建議先閱讀前一篇文章:《前端面試題:手寫bind》。

new

我們先學(xué)習(xí)一下new操作符。

new用于通過函數(shù)來創(chuàng)建一個對象實(shí)例,在很多語言中都能看到。

JS的函數(shù),除了可以是普通函數(shù),比如:

functionsum(a,b){

returna+b;

還可以是構(gòu)造函數(shù),只需要在構(gòu)造時在它前面加一個new:

functionPerson(name,age){

=name;

this.age=age;

constperson=newPerson('前端西瓜哥',100)

//Person{name:'前端西瓜哥',age:100}

new創(chuàng)建一個新對象,做了下面幾件事:

創(chuàng)建一個空對象{};空對象的原型屬性__proto__指向構(gòu)造函數(shù)的原型對象Ptotype;函數(shù)中的this設(shè)置為這個空對象;如果該函數(shù)不返回一個對象,就返回這個this,否則返回這個對象。

判斷函數(shù)是否通過new被調(diào)用

怎么判斷一個函數(shù)正在被new操作符調(diào)用?

答案是使用instanceof判斷this是否為當(dāng)前函數(shù)的實(shí)例,即thisinstanceofFn為true,表示在通過new構(gòu)建實(shí)例。

我們看一個例子:

functionPerson(){

if(thisinstanceofPerson){

console.log('通過new構(gòu)建實(shí)例');

}else{

console.log('普通調(diào)用')

Person()//輸出:普通調(diào)用

newPerson()//輸出:通過new構(gòu)建實(shí)例

在Vuejs的源碼,你會看到下面代碼,這里也用到了這個技巧。

functionVue(options){

if(__DEV__!(thisinstanceofVue)){

warn('Vueisaconstructorandshouldbecalledwiththe`new`keyword')

this._init(options)

你在開發(fā)環(huán)境如果不通過new來使用Vue對象,會在控制臺提示你要通過new來調(diào)用Vue。

new和bind

如果我們new的是Ftotype.bind返回的新函數(shù),會發(fā)生什么事情?

functionPerson(name,age){

=name;

this.age=age;

constBoundPerson=Person.bind(null,'前端西瓜哥');

constboundPerson=newBoundPerson(100);

//Person{name:'前端西瓜哥',age:100}

boundPerson.__proto__===Ptotype

//true

結(jié)果等價于直接去new原始函數(shù)。

不同的是,仍舊可以進(jìn)行參數(shù)的預(yù)置。可以看到,構(gòu)造函數(shù)的第一個參數(shù),在調(diào)用bind的時候就提前設(shè)置為前端西瓜哥。

實(shí)現(xiàn)完整的bind

完整實(shí)現(xiàn)如下:

Ftotype.myBind=function(thisArg,...prefixArgs){

constfn=this;

constboundFn=function(...args){

//通過new使用當(dāng)前函數(shù)

if(thisinstanceofboundFn){

returnnewfn(...prefixArgs,...args);

//普通的方法調(diào)用當(dāng)前函數(shù)

returnfn.call(thisArg,...prefixArgs,...args);

boundFtotype=totype;

returnboundFn;

這里我通過thisinstanceofboundFn來判斷是否用了new,如果是,就直接new原始函數(shù)然后返回,記得帶上bind預(yù)置好的參數(shù)。

其他保持原樣(具體見上文《前端面試題:手寫bind》)。

boundFtotype=totype;這個可寫可不寫,只是讓bind返回的新函數(shù)的prototype指向原函數(shù)的prototype。

如果是原生bind返回的函數(shù),它是沒有protoype屬性的,可以認(rèn)為它是一種特別的函數(shù),而我們實(shí)現(xiàn)的bind返回的卻是一個普通函數(shù),所以并不能完全模擬的。

如果你追求完美的實(shí)現(xiàn),可以研讀一下Ftotype.bind的標(biāo)準(zhǔn):

然后再看看知名的core.js庫中對bind的實(shí)現(xiàn):

其中核心實(shí)現(xiàn)為:

//`Ftotype.bind`methodimplementation

//https://tc39.es/ecma262/#totype.bind

module.exports=Function.bind||functionbind(that/*,...args*/){

varF=aCallable(this);

varPrototype=F.prototype;

varpartArgs=arraySlice(arguments,1);

varboundFunction=functionbound(/*args...*/){

varargs=concat(partArgs,arraySlice(arguments));

returnthisinstanceofboundFunctionconstruct(F,args.length,args):F.apply(that,args);

if(isObject(Prototype))boundFtotype=Prototype;

returnboundFunction;

這里有更多的細(xì)節(jié):

這里判斷了this是否為函數(shù)類型,不是函數(shù)會報錯;F.prototype需要是一個對象或函數(shù),才能賦值給新函數(shù);使用了普通函數(shù)和arguments,這是為了兼容ES5

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論