亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JavaScript 鏈式結構序列化詳解

 更新時間:2016年09月30日 14:09:25   作者:猴子猿  
這篇文章主要介紹了JavaScript 鏈式結構序列化詳解的相關資料,需要的朋友可以參考下

一、概述

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

if_else:

if(...){
  //TODO
}else if(...){
  //TODO
}else{
  //TODO
}

switch:

switch(name){
  case ...:{
    //TODO
    break;
  }
  case ...:{
    //TODO
    break;
  }
  default:{
    //TODO  
  }
}

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

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

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

二、鏈式代碼扁平化

假如,現(xiàn)在我們有如下鏈式代碼:

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ù)結構中的單鏈表,那么,初步利用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ù),并且我們假設,如果諸如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);

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

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ù)組時,都復制粘貼一遍方法吧,所以重構代碼如下:

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)建一遍是不科學的,so,利用prototype在原有的基礎上繼續(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();

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

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

三、異步代碼鏈式扁平化

在上面我們討論的都是同步過程,倘若,鏈式調用函數(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變成了異步,按照上述代碼的邏輯,應該是等f1完全執(zhí)行完畢(包括setTimeout執(zhí)行)后,判斷是否執(zhí)行f2,但真的如此嗎?

測試代碼如下:

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

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

Why?

因為JavaScript是單線程嘛。詳情見(here)

那該怎么解決呢?

由于有異步代碼,且必須在異步代碼后處理后續(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方法,固,需細微調整Slink構造函數(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);

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

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

感謝閱讀此文,希望能幫助到大家,謝謝大家對本站的支持!

相關文章

  • JavaScript的繼承實現(xiàn)小結

    JavaScript的繼承實現(xiàn)小結

    JavaScript作為面向對象的弱類型語言,繼承也是其非常強大的特性之一。那么如何在JS中實現(xiàn)繼承呢?本文將給大家揭開神秘面紗
    2017-05-05
  • 前后臺交互過程中json格式如何解析以及如何生成

    前后臺交互過程中json格式如何解析以及如何生成

    json格式想必大家會很熟悉;因為他在ajax異步應用中會顯得很有魅力,有些新手朋友對其有點陌生,接下來介紹前臺如何解析json格式以及后臺如何生成json格式等,需要了解的朋友可以參考下
    2012-12-12
  • 為JS擴展Array.prototype.indexOf引發(fā)的問題及解決辦法

    為JS擴展Array.prototype.indexOf引發(fā)的問題及解決辦法

    這篇文章主要介紹了為JS擴展Array.prototype.indexOf引發(fā)的問題及解決辦法,需要的朋友可以參考下
    2015-01-01
  • JS中Object.assign方法的使用

    JS中Object.assign方法的使用

    這篇文章介紹了JS中Object.assign方法的使用方式,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • 淺談javascript:兩種注釋,聲明變量,定義函數(shù)

    淺談javascript:兩種注釋,聲明變量,定義函數(shù)

    下面小編就為大家?guī)硪黄獪\談javascript:兩種注釋,聲明變量,定義函數(shù)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • JavaScript字符串處理(String對象)詳解

    JavaScript字符串處理(String對象)詳解

    這篇文章主要介紹了JavaScript字符串處理(String對象)詳解,本文列出并詳細講解了String對象的一些方法,需要的朋友可以參考下
    2014-10-10
  • 怎樣在JavaScript里寫一個swing把數(shù)據(jù)插入數(shù)據(jù)庫

    怎樣在JavaScript里寫一個swing把數(shù)據(jù)插入數(shù)據(jù)庫

    在JavaScript里寫一個swing來實現(xiàn)確定取消,來決定是否執(zhí)行這個功能 控制把數(shù)據(jù)插入數(shù)據(jù)庫,接下來介紹實現(xiàn)方法
    2012-12-12
  • JavaScript 學習初步 入門教程

    JavaScript 學習初步 入門教程

    看了《21天學習JavaScript》的視頻教程,感覺就是語法好熟悉,和C++類似,和C#類似,和Java類似!幡然悔悟這些語言的語法都是類似的,數(shù)據(jù)類型,對象方法(或者稱之為函數(shù),由于我是個菜鳥所以也數(shù)不清楚到底是什么)。
    2010-03-03
  • 簡單總結JavaScript中的String字符串類型

    簡單總結JavaScript中的String字符串類型

    就像其他語言那樣,js中的字符串類型可以表示一串字符,由雙引號包住,這里簡單總結JavaScript中的String字符串類型的一些基礎知識
    2016-05-05
  • ajax的hide隱藏問題解決方法

    ajax的hide隱藏問題解決方法

    我的頁面上有兩個table,調用ajax之后隱藏掉一個,然后用html拼出另一個table,結果新的table最上面有個undefined,這個是怎么引起的
    2012-12-12

最新評論