成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

JavaScript鏈式結構序列化詳解

開發 前端
在JavaScript中,鏈式模式代碼,太多太多,下面我們就來一起嘗試實現下。

[[179272]]

一、概述

在JavaScript中,鏈式模式代碼,太多太多,如下:

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

疑問:諸如上述這些鏈式代碼,倘若,我們想將其扁平化鏈式處理呢?如下:

 

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

下面我們就來一起嘗試實現下唄。

二、鏈式代碼扁平化

假如,現在我們有如下鏈式代碼:

 

  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!'); 

好了,現在我們一步一步將其”扁平化”。

其實看看上面的代碼,不難發現,if…else這種格式,其實就是數據結構中的單鏈表,那么,初步利用JavaScript實現單鏈表,如下:

 

  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為判斷函數,并且我們假設,如果諸如f1、f2、f3返回’next’時,就繼續往下查找,否則,停止往下查找。如下:

 

  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!'); 

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

但是,我們的最終目的是想實現如下這樣的呢?

 

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

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

 

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

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

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

 

  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中的,總不能每次創建一個數組時,都復制粘貼一遍方法吧,所以重構代碼如下:

 

  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這種公共方法,在每次實例化時,都創建一遍是不科學的,so,利用prototype在原有的基礎上繼續變形,如下:

 

  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這個過程,封裝到函數中,如同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(); 

當然,除開利用數組這種方式,還可以利用閉包,實現鏈式扁平化效果,如下:

 

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

三、異步代碼鏈式扁平化

在上面我們討論的都是同步過程,倘若,鏈式調用函數中有異步情況呢?

什么意思?如下:

 

  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變成了異步,按照上述代碼的邏輯,應該是等f1完全執行完畢(包括setTimeout執行)后,判斷是否執行f2,但真的如此嗎?

測試代碼如下:

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

執行代碼的結果就是,什么也不輸出。

Why?

因為JavaScript是單線程嘛。

那該怎么解決呢?

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

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

好了,由于在函數中,我們使用了this,其代表Slink對象,且改變了resolve方法,固,需細微調整Slink構造函數和原型鏈,如下:

  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.             //處理后續鏈 
  7.             this.resolve(name, 1);//1代表下一個需處理函數在數組中的位置 
  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,是不是感覺這么相似呢。

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

責任編輯:張燕妮 來源: 猴子猿
相關推薦

2009-08-06 11:16:25

C#序列化和反序列化

2009-09-09 15:47:27

XML序列化和反序列化

2022-08-06 08:41:18

序列化反序列化Hessian

2009-08-19 10:13:22

Remoting序列化

2016-09-21 00:15:27

2024-05-06 00:00:00

C#序列化技術

2010-02-22 16:00:22

WCF序列化

2011-06-01 15:05:02

序列化反序列化

2009-08-24 17:14:08

C#序列化

2011-05-18 15:20:13

XML

2023-12-13 13:49:52

Python序列化模塊

2018-03-19 10:20:23

Java序列化反序列化

2010-01-05 16:31:45

.NET Framew

2024-09-25 16:10:05

2013-03-11 13:55:03

JavaJSON

2011-06-01 14:50:48

2019-11-20 10:07:23

web安全PHP序列化反序列化

2009-06-14 22:01:27

Java對象序列化反序列化

2009-08-25 14:24:36

C#序列化和反序列化

2011-06-01 14:26:11

序列化
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久免费大片 | 成人影院av| 在线观看国产 | 日本一区二区三区在线观看 | 99精品一区 | 国产成人a亚洲精品 | 日韩一区二区三区四区五区 | 一区二区福利视频 | 免费一区二区 | av片在线播放 | 激情欧美一区二区三区中文字幕 | 91在线视频播放 | 久久国产综合 | 日本一区二区三区四区 | 成年人视频在线免费观看 | 91看片网 | 国产免费av在线 | 日日精品 | 国产乱码精品一区二区三区忘忧草 | 精品久久久久久久久久久久久久 | 亚洲成人精品一区 | 亚洲精品一区二区三区四区高清 | 欧美区日韩区 | 亚洲精品免费视频 | 久久久91 | 亚洲成人综合在线 | 成人免费视频 | 日韩在线精品视频 | 成人福利视频网站 | 爱草在线| 精品视频免费 | 亚洲天堂一区 | 国产精品爱久久久久久久 | 亚洲成人观看 | 国产一区二区在线免费观看 | h视频在线免费观看 | 亚欧洲精品在线视频免费观看 | 天天草av| 一区二区三区在线播放视频 | 国产精品女人久久久 | aa级毛片毛片免费观看久 |