自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

JavaScript鏈?zhǔn)浇Y(jié)構(gòu)序列化詳解

開(kāi)發(fā) 前端
在JavaScript中,鏈?zhǔn)侥J酱a,太多太多,下面我們就來(lái)一起嘗試實(shí)現(xiàn)下。

[[179272]]

一、概述

在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.     } 

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

 

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

下面我們就來(lái)一起嘗試實(shí)現(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)在我們一步一步將其”扁平化”。

其實(shí)看看上面的代碼,不難發(fā)現(xiàn),if…else這種格式,其實(shí)就是數(shù)據(jù)結(jié)構(gòu)中的單鏈表,那么,初步利用JavaScript實(shí)現(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’時(shí),就繼續(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!'); 

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

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

 

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

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

 

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

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

So,那我們只能新寫(xiě)一個(gè)add方法,效果和push一樣,但是返回?cái)?shù)組對(duì)象。如下:

 

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

測(cè)試代碼如下:

 

  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(); 

但是,這樣有個(gè)缺點(diǎn),我們是將add、resolve方法綁定在全局變量thens中的,總不能每次創(chuàng)建一個(gè)數(shù)組時(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這種公共方法,在每次實(shí)例化時(shí),都創(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.     } 

測(cè)試代碼如下:

 

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

不錯(cuò),但是這樣,我們每次都得手動(dòng)new一個(gè)Slink,有點(diǎn)麻煩,所以,我們將new Slink這個(gè)過(guò)程,封裝到函數(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.     } 

測(cè)試代碼如下:

 

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

好了,大功告成,接下來(lái)就是語(yǔ)法糖滴問(wèn)題咯,整理代碼如下:

 

  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.     } 

測(cè)試代碼如下:

 

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

當(dāng)然,除開(kāi)利用數(shù)組這種方式,還可以利用閉包,實(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.     } 

測(cè)試代碼如下:

 

  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>

在上面我們討論的都是同步過(guò)程,倘若,鏈?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)該是等f(wàn)1完全執(zhí)行完畢(包括setTimeout執(zhí)行)后,判斷是否執(zhí)行f2,但真的如此嗎?

測(cè)試代碼如下:

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

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

Why?

因?yàn)镴avaScript是單線程嘛。

那該怎么解決呢?

由于有異步代碼,且必須在異步代碼后處理后續(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代表下一個(gè)需處理函數(shù)在數(shù)組中的位置 
  8.         } 
  9.     }.bind(this), 2000); 

好了,由于在函數(shù)中,我們使用了this,其代表Slink對(duì)象,且改變了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.     } 

測(cè)試代碼如下:

  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代表下一個(gè)需處理函數(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,是不是感覺(jué)這么相似呢。

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

責(zé)任編輯:張燕妮 來(lái)源: 猴子猿
相關(guān)推薦

2009-08-06 11:16:25

C#序列化和反序列化

2009-09-09 15:47:27

XML序列化和反序列化

2022-08-06 08:41:18

序列化反序列化Hessian

2024-05-06 00:00:00

C#序列化技術(shù)

2009-08-19 10:13:22

Remoting序列化

2016-09-21 00:15:27

2010-02-22 16:00:22

WCF序列化

2009-08-24 17:14:08

C#序列化

2011-06-01 15:05:02

序列化反序列化

2024-09-25 16:10:05

2010-01-05 16:31:45

.NET Framew

2023-12-13 13:49:52

Python序列化模塊

2011-05-18 15:20:13

XML

2018-03-19 10:20:23

Java序列化反序列化

2009-06-14 22:01:27

Java對(duì)象序列化反序列化

2019-11-20 10:07:23

web安全PHP序列化反序列化

2009-08-25 14:24:36

C#序列化和反序列化

2011-06-01 14:50:48

2013-03-11 13:55:03

JavaJSON

2011-06-01 14:26:11

序列化
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)