您好,登錄后才能下訂單哦!
這篇文章主要介紹了JavaScript如何實現(xiàn)序列化鏈?zhǔn)浇Y(jié)構(gòu)的相關(guān)知識,內(nèi)容詳細(xì)易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇JavaScript如何實現(xiàn)序列化鏈?zhǔn)浇Y(jié)構(gòu)文章都會有所收獲,下面我們一起來看看吧。
一、概述
在JavaScript中,鏈?zhǔn)侥J酱a,太多太多,如下:
if_else:
if(...){ //TODO }else if(...){ //TODO }else{ //TODO }
switch:
switch(name){ case ...:{ //TODO break; } case ...:{ //TODO break; } default:{ //TODO } }
疑問:諸如上述這些鏈?zhǔn)酱a,倘若,我們想將其扁平化鏈?zhǔn)教幚砟??如下?/p>
//fn1,f2,f3為處理函數(shù) _if(fn1)._elseIf(fn2)._else(fn3);
下面我們就來一起嘗試實現(xiàn)下唄。
二、鏈?zhǔn)酱a扁平化
假如,現(xiàn)在我們有如下鏈?zhǔn)酱a:
if(name === 'Monkey'){ console.log('yes, I am Monkey'); }else if(name === 'Dorie'){ console.log('yes, I am Dorie'); }else{ console.log('sorry, over for ending!'); }
好了,現(xiàn)在我們一步一步將其”扁平化”。
其實看看上面的代碼,不難發(fā)現(xiàn),if…else這種格式,其實就是數(shù)據(jù)結(jié)構(gòu)中的單鏈表,那么,初步利用JavaScript實現(xiàn)單鏈表,如下:
var thens = []; thens.resolve = function(name){ for(var i = 0, len = this.length; i < len;i++){ if(this[i](name) !== 'next'){ break; } } } thens.push(f1, f2, f3);
其中f1,f2,f3為判斷函數(shù),并且我們假設(shè),如果諸如f1、f2、f3返回’next’時,就繼續(xù)往下查找,否則,停止往下查找。如下:
function f1(name){ if(name === 'Monkey'){ console.log('yes, I am Monkey'); }else{ return 'next'; } } function f2(name){ if(name === 'Dorie'){ console.log('yes, I am Dorie'); }else{ return 'next'; } } function f3(){ console.log('sorry, over for ending!'); }
好了,這就是鏈表的模式。
但是,我們的最終目的是想實現(xiàn)如下這樣的呢?
//fn1,f2,f3為處理函數(shù) _if(fn1)._elseIf(fn2)._else(fn3);
你可能會說,將上述代碼改成如下這樣,不就好了嗎??。?/p>
thens.push(f1).push(f2).push(f3).resolve();
But,JavaScript的push方法返回的是數(shù)組的新長度,而不是數(shù)組對象哦。
So,那我們只能新寫一個add方法,效果和push一樣,但是返回數(shù)組對象。如下:
thens.add = function(f){ if(typeof f === 'function'){ this.push(f); return this; } }
測試代碼如下:
var thens = []; thens.add = function(f){ if(typeof f === 'function'){ this.push(f); return this; } } thens.resolve = function(name){ for(var i = 0, len = this.length; i < len;i++){ if(this[i](name) !== 'next'){ break; } } } thens.add(f1).add(f2).add(f3).resolve();
但是,這樣有個缺點,我們是將add、resolve方法綁定在全局變量thens中的,總不能每次創(chuàng)建一個數(shù)組時,都復(fù)制粘貼一遍方法吧,所以重構(gòu)代碼如下:
function Slink(){ this.thens = []; this.thens.add = function(f){ if(typeof f === 'function'){ this.push(f); return this; } } this.thens.resolve = function(name){ for(var i = 0, len = this.length; i < len;i++){ if(this[i](name) !== 'next'){ break; } } } }
顯然,add,resolve這種公共方法,在每次實例化時,都創(chuàng)建一遍是不科學(xué)的,so,利用prototype在原有的基礎(chǔ)上繼續(xù)變形,如下:
function Slink(){ this.thens = []; } Slink.prototype = { add: function(f){ if(typeof f === 'function'){ this.thens.push(f); return this; } }, resolve: function(name){ for(var i = 0, len = this.thens.length; i < len; i++){ if(this.thens[i](name) !== 'next'){ break; } } } }
測試代碼如下:
var thens = new Slink(); thens.add(f1).add(f2).add(f3); thens.resolve();
不錯,但是這樣,我們每次都得手動new一個Slink,有點麻煩,所以,我們將new Slink這個過程,封裝到函數(shù)中,如同jQuery一樣,如下:
function $go(f){ return new Slink(f); } function Slink(f){ this.thens = []; this.thens.push(f); } Slink.prototype = { add: function(f){ if(typeof f === 'function'){ this.thens.push(f); return this; } }, resolve: function(name){ for(var i = 0, len = this.thens.length; i < len; i++){ if(this.thens[i](name) !== 'next'){ break; } } } }
測試代碼如下:
$go(f1).add(f2).add(f3).resolve();
好了,大功告成,接下來就是語法糖滴問題咯,整理代碼如下:
function _if(f){ return new Slink(f); } function Slink(f){ this.thens = []; this.thens.push(f); } Slink.prototype = { _elseIf: function(f){ if(typeof f === 'function'){ this.thens.push(f); return this; } }, _else: function(f){ return this._elseIf(f); }, resolve: function(name){ for(var i = 0, len = this.thens.length; i < len; i++){ if(this.thens[i](name) !== 'next'){ break; } } return this; } }
測試代碼如下:
_if(f1)._elseIf(f2)._else(f3).resolve();
當(dāng)然,除開利用數(shù)組這種方式,還可以利用閉包,實現(xiàn)鏈?zhǔn)奖馄交Ч?,如下?/p>
var func = Function.prototype; func._else = func._elseIf = function(fn){ var _this = this; return function(){ var res = _this.apply(this,arguments); if(res==="next"){ //值為Boolean return fn.apply(this,arguments); } return res; } }
測試代碼如下:
function f1(name){ if(name === 'Monkey'){ console.log('yes, I am Monkey'); }else{ return 'next'; } } function f2(name){ if(name === 'Dorie'){ console.log('yes, I am Dorie'); }else{ return 'next'; } } function f3(){ console.log('sorry, over for ending!'); } f1._elseIf(f2)._else(f3)('Dorie');
三、異步代碼鏈?zhǔn)奖馄交?/strong>
在上面我們討論的都是同步過程,倘若,鏈?zhǔn)秸{(diào)用函數(shù)中有異步情況呢?
什么意思?如下:
function f1(name){ setTimeout(function(){ if(name === 'Monkey'){ console.log('yes, I am Monkey'); }else{ return 'next'; } }, 2000); } function f2(name){ if(name === 'Dorie'){ console.log('yes, I am Dorie'); }else{ return 'next'; } } function f3(){ console.log('sorry, over for ending!'); }
我們將f1利用setTimeout變成了異步,按照上述代碼的邏輯,應(yīng)該是等f1完全執(zhí)行完畢(包括setTimeout執(zhí)行)后,判斷是否執(zhí)行f2,但真的如此嗎?
測試代碼如下:
_if(f1)._elseIf(f2)._else(f3).resolve();
執(zhí)行代碼的結(jié)果就是,什么也不輸出。
Why?
因為JavaScript是單線程嘛。
那該怎么解決呢?
由于有異步代碼,且必須在異步代碼后處理后續(xù)的鏈,那么我們就等待異步代碼執(zhí)行完畢后,才執(zhí)行后續(xù)的鏈嘛,如下:
function f1(name){ setTimeout(function(){ if(name === 'Monkey'){ console.log('yes, I am Monkey'); }else{ //處理后續(xù)鏈 this.resolve(name, 1);//1代表下一個需處理函數(shù)在數(shù)組中的位置 } }.bind(this), 2000); }
好了,由于在函數(shù)中,我們使用了this,其代表Slink對象,且改變了resolve方法,固,需細(xì)微調(diào)整Slink構(gòu)造函數(shù)和原型鏈,如下:
function Slink(f){ this.thens = []; this.thens.push(f.bind(this)); } Slink.prototype = { _elseIf: function(f){ if(typeof f === 'function'){ this.thens.push(f.bind(this)); return this; } }, _else: function(f){ return this._elseIf(f.bind(this)); }, resolve: function(name, flag){ for(var i = flag, len = this.thens.length; i < len; i++){ if(this.thens[i](name) !== 'next'){ break; } } return this; } }
測試代碼如下:
function f1(name){ setTimeout(function(){ if(name === 'Monkey'){ console.log('yes, I am Monkey'); }else{ //處理后續(xù)鏈 this.resolve(name, 1);//1代表下一個需處理函數(shù)在數(shù)組中的位置 } }.bind(this), 2000); } function f2(name){ if(name === 'Dorie'){ console.log('yes, I am Dorie'); }else{ return 'next'; } } function f3(){ console.log('sorry, over for ending!'); } _if(f1)._elseIf(f2)._else(f3).resolve('',0);
關(guān)于“JavaScript如何實現(xiàn)序列化鏈?zhǔn)浇Y(jié)構(gòu)”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“JavaScript如何實現(xiàn)序列化鏈?zhǔn)浇Y(jié)構(gòu)”知識都有一定的了解,大家如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。