日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
JavaScript鏈?zhǔn)浇Y(jié)構(gòu)序列化詳解

一、概述

創(chuàng)新互聯(lián)公司堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站設(shè)計、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的黔江網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

在JavaScript中,鏈?zhǔn)侥J酱a,太多太多,如下:

if_else:

 
 
  1. if(...){ 
  2.     //TODO 
  3. }else if(...){ 
  4.     //TODO 
  5. }else{ 
  6.     //TODO 

switch:

 
 
  1. switch(name){ 
  2.     case ...:{ 
  3.         //TODO 
  4.         break; 
  5.     } 
  6.     case ...:{ 
  7.         //TODO 
  8.         break; 
  9.     } 
  10.     default:{ 
  11.         //TODO     
  12.     } 

疑問:諸如上述這些鏈?zhǔn)酱a,倘若,我們想將其扁平化鏈?zhǔn)教幚砟??如下?/p>

 
 
  1. //fn1,f2,f3為處理函數(shù) 
  2. _if(fn1)._elseIf(fn2)._else(fn3); 

下面我們就來一起嘗試實現(xiàn)下唄。

二、鏈?zhǔn)酱a扁平化

假如,現(xiàn)在我們有如下鏈?zhǔn)酱a:

 
 
  1. if(name === 'Monkey'){ 
  2.     console.log('yes, I am Monkey'); 
  3. }else if(name === 'Dorie'){ 
  4.     console.log('yes, I am Dorie'); 
  5. }else{ 
  6.     console.log('sorry, over for ending!'); 

好了,現(xiàn)在我們一步一步將其”扁平化”。

其實看看上面的代碼,不難發(fā)現(xiàn),if…else這種格式,其實就是數(shù)據(jù)結(jié)構(gòu)中的單鏈表,那么,初步利用JavaScript實現(xiàn)單鏈表,如下:

 
 
  1. var thens = []; 
  2. thens.resolve = function(name){ 
  3.     for(var i = 0, len = this.length; i < len;i++){ 
  4.         if(this[i](name) !== 'next'){ 
  5.             break; 
  6.         } 
  7.     } 
  8. thens.push(f1, f2, f3); 

其中f1,f2,f3為判斷函數(shù),并且我們假設(shè),如果諸如f1、f2、f3返回’next’時,就繼續(xù)往下查找,否則,停止往下查找。如下:

 
 
  1. function f1(name){ 
  2.     if(name === 'Monkey'){ 
  3.         console.log('yes, I am Monkey'); 
  4.     }else{ 
  5.         return 'next'; 
  6.     } 
  7. function f2(name){ 
  8.     if(name === 'Dorie'){ 
  9.         console.log('yes, I am Dorie'); 
  10.     }else{ 
  11.         return 'next'; 
  12.     } 
  13. function f3(){ 
  14.     console.log('sorry, over for ending!'); 

好了,這就是鏈表的模式。

但是,我們的最終目的是想實現(xiàn)如下這樣的呢?

 
 
  1. //fn1,f2,f3為處理函數(shù) 
  2. _if(fn1)._elseIf(fn2)._else(fn3); 

你可能會說,將上述代碼改成如下這樣,不就好了嗎???!

 
 
  1. thens.push(f1).push(f2).push(f3).resolve(); 

But,JavaScript的push方法返回的是數(shù)組的新長度,而不是數(shù)組對象哦。

So,那我們只能新寫一個add方法,效果和push一樣,但是返回數(shù)組對象。如下:

 
 
  1. thens.add = function(f){ 
  2.     if(typeof f === 'function'){ 
  3.         this.push(f); 
  4.         return this;         
  5.     }         

測試代碼如下:

 
 
  1. var thens = []; 
  2. thens.add = function(f){ 
  3.     if(typeof f === 'function'){ 
  4.         this.push(f); 
  5.         return this;         
  6.     }         
  7. thens.resolve = function(name){ 
  8.     for(var i = 0, len = this.length; i < len;i++){ 
  9.         if(this[i](name) !== 'next'){ 
  10.             break; 
  11.         } 
  12.     }     
  13. thens.add(f1).add(f2).add(f3).resolve(); 

但是,這樣有個缺點,我們是將add、resolve方法綁定在全局變量thens中的,總不能每次創(chuàng)建一個數(shù)組時,都復(fù)制粘貼一遍方法吧,所以重構(gòu)代碼如下:

 
 
  1. function Slink(){ 
  2.     this.thens = []; 
  3.     this.thens.add = function(f){ 
  4.         if(typeof f === 'function'){ 
  5.             this.push(f); 
  6.             return this;         
  7.         }         
  8.     } 
  9.     this.thens.resolve = function(name){ 
  10.         for(var i = 0, len = this.length; i < len;i++){ 
  11.             if(this[i](name) !== 'next'){ 
  12.                 break; 
  13.             } 
  14.         }     
  15.     } 

顯然,add,resolve這種公共方法,在每次實例化時,都創(chuàng)建一遍是不科學(xué)的,so,利用prototype在原有的基礎(chǔ)上繼續(xù)變形,如下:

 
 
  1. function Slink(){ 
  2.     this.thens = []; 
  3. Slink.prototype = { 
  4.     add: function(f){ 
  5.             if(typeof f === 'function'){ 
  6.                 this.thens.push(f); 
  7.                 return this;         
  8.             }         
  9.     }, 
  10.     resolve: function(name){ 
  11.             for(var i = 0, len = this.thens.length; i < len; i++){ 
  12.                 if(this.thens[i](name) !== 'next'){ 
  13.                     break; 
  14.                 } 
  15.             }     
  16.     } 

測試代碼如下:

 
 
  1. var thens = new Slink(); 
  2. thens.add(f1).add(f2).add(f3); 
  3. thens.resolve(); 

不錯,但是這樣,我們每次都得手動new一個Slink,有點麻煩,所以,我們將new Slink這個過程,封裝到函數(shù)中,如同jQuery一樣,如下:

 
 
  1. function $go(f){ 
  2.     return new Slink(f); 
  3. function Slink(f){ 
  4.     this.thens = []; 
  5.     this.thens.push(f); 
  6. Slink.prototype = { 
  7.     add: function(f){ 
  8.             if(typeof f === 'function'){ 
  9.                 this.thens.push(f); 
  10.                 return this;         
  11.             }         
  12.     }, 
  13.     resolve: function(name){ 
  14.             for(var i = 0, len = this.thens.length; i < len; i++){ 
  15.                 if(this.thens[i](name) !== 'next'){ 
  16.                     break; 
  17.                 } 
  18.             }     
  19.     } 

測試代碼如下:

 
 
  1. $go(f1).add(f2).add(f3).resolve(); 

好了,大功告成,接下來就是語法糖滴問題咯,整理代碼如下:

 
 
  1. function _if(f){ 
  2.     return new Slink(f); 
  3. function Slink(f){ 
  4.     this.thens = []; 
  5.     this.thens.push(f); 
  6. Slink.prototype = { 
  7.     _elseIf: function(f){ 
  8.             if(typeof f === 'function'){ 
  9.                 this.thens.push(f); 
  10.                 return this;         
  11.             }         
  12.     }, 
  13.     _else: function(f){ 
  14.             return this._elseIf(f); 
  15.     }, 
  16.     resolve: function(name){ 
  17.             for(var i = 0, len = this.thens.length; i < len; i++){ 
  18.                 if(this.thens[i](name) !== 'next'){ 
  19.                     break; 
  20.                 } 
  21.             } 
  22.             return this;             
  23.     } 

測試代碼如下:

 
 
  1. _if(f1)._elseIf(f2)._else(f3).resolve(); 

當(dāng)然,除開利用數(shù)組這種方式,還可以利用閉包,實現(xiàn)鏈?zhǔn)奖馄交Ч?,如下?/p>

 
 
  1. var func = Function.prototype; 
  2. func._else = func._elseIf = function(fn){ 
  3.     var _this = this; 
  4.     return function(){ 
  5.         var res = _this.apply(this,arguments); 
  6.         if(res==="next"){  //值為Boolean 
  7.             return fn.apply(this,arguments); 
  8.         } 
  9.         return res; 
  10.     } 

測試代碼如下:

 
 
  1. function f1(name){ 
  2.     if(name === 'Monkey'){ 
  3.         console.log('yes, I am Monkey'); 
  4.     }else{ 
  5.         return 'next'; 
  6.     } 
  7. function f2(name){ 
  8.     if(name === 'Dorie'){ 
  9.         console.log('yes, I am Dorie'); 
  10.     }else{ 
  11.         return 'next'; 
  12.     } 
  13. function f3(){ 
  14.     console.log('sorry, over for ending!'); 
  15. f1._elseIf(f2)._else(f3)('Dorie'); 

三、異步代碼鏈?zhǔn)奖馄交?/strong>

在上面我們討論的都是同步過程,倘若,鏈?zhǔn)秸{(diào)用函數(shù)中有異步情況呢?

什么意思?如下:

 
 
  1. function f1(name){ 
  2.     setTimeout(function(){ 
  3.         if(name === 'Monkey'){ 
  4.             console.log('yes, I am Monkey'); 
  5.         }else{ 
  6.             return 'next'; 
  7.         } 
  8.     }, 2000); 
  9. function f2(name){ 
  10.     if(name === 'Dorie'){ 
  11.         console.log('yes, I am Dorie'); 
  12.     }else{ 
  13.         return 'next'; 
  14.     } 
  15. function f3(){ 
  16.     console.log('sorry, over for ending!'); 

我們將f1利用setTimeout變成了異步,按照上述代碼的邏輯,應(yīng)該是等f1完全執(zhí)行完畢(包括setTimeout執(zhí)行)后,判斷是否執(zhí)行f2,但真的如此嗎?

測試代碼如下:

 
 
  1. _if(f1)._elseIf(f2)._else(f3).resolve(); 

執(zhí)行代碼的結(jié)果就是,什么也不輸出。

Why?

因為JavaScript是單線程嘛。

那該怎么解決呢?

由于有異步代碼,且必須在異步代碼后處理后續(xù)的鏈,那么我們就等待異步代碼執(zhí)行完畢后,才執(zhí)行后續(xù)的鏈嘛,如下:

 
 
  1. function f1(name){ 
  2.     setTimeout(function(){ 
  3.         if(name === 'Monkey'){ 
  4.             console.log('yes, I am Monkey'); 
  5.         }else{ 
  6.             //處理后續(xù)鏈 
  7.             this.resolve(name, 1);//1代表下一個需處理函數(shù)在數(shù)組中的位置 
  8.         } 
  9.     }.bind(this), 2000); 

好了,由于在函數(shù)中,我們使用了this,其代表Slink對象,且改變了resolve方法,固,需細(xì)微調(diào)整Slink構(gòu)造函數(shù)和原型鏈,如下:

 
 
  1. function Slink(f){ 
  2.     this.thens = []; 
  3.     this.thens.push(f.bind(this)); 
  4. Slink.prototype = { 
  5.     _elseIf: function(f){ 
  6.             if(typeof f === 'function'){ 
  7.                 this.thens.push(f.bind(this)); 
  8.                 return this;        
  9.             }        
  10.     }, 
  11.     _else: function(f){ 
  12.             return this._elseIf(f.bind(this)); 
  13.     }, 
  14.     resolve: function(name, flag){ 
  15.             for(var i = flag, len = this.thens.length; i < len; i++){ 
  16.                 if(this.thens[i](name) !== 'next'){ 
  17.                     break; 
  18.                 } 
  19.             } 
  20.             return this;            
  21.     } 

測試代碼如下:

 
 
  1. function f1(name){ 
  2.     setTimeout(function(){ 
  3.         if(name === 'Monkey'){ 
  4.             console.log('yes, I am Monkey'); 
  5.         }else{ 
  6.             //處理后續(xù)鏈 
  7.             this.resolve(name, 1);//1代表下一個需處理函數(shù)在數(shù)組中的位置 
  8.         } 
  9.     }.bind(this), 2000); 
  10. function f2(name){ 
  11.     if(name === 'Dorie'){ 
  12.         console.log('yes, I am Dorie'); 
  13.     }else{ 
  14.         return 'next'; 
  15.     } 
  16. function f3(){ 
  17.     console.log('sorry, over for ending!'); 
  18. _if(f1)._elseIf(f2)._else(f3).resolve('',0); 

哈哈,如果你了解Promise,是不是感覺這么相似呢。

是的,宗旨都一樣,達(dá)到異步代碼扁平化目的,不過這里的代碼比Promise要簡約得多啦。


分享題目:JavaScript鏈?zhǔn)浇Y(jié)構(gòu)序列化詳解
文章地址:http://www.dlmjj.cn/article/dhggdoc.html