Heim > Web-Frontend > js-Tutorial > Hauptteil

Detaillierte Erläuterung der Serialisierung der JavaScript-Kettenstruktur

黄舟
Freigeben: 2017-03-04 15:21:22
Original
1100 Leute haben es durchsucht

1. Übersicht

In JavaScript gibt es zu viele Kettenmustercodes, wie folgt:

if_else:

if(...){
    //TODO
}else if(...){
    //TODO
}else{
    //TODO
}
Nach dem Login kopieren

Schalter:

switch(name){
    case ...:{
        //TODO
        break;
    }
    case ...:{
        //TODO
        break;
    }
    default:{
        //TODO    
    }
}
Nach dem Login kopieren

Frage: Wie der obige Kettencode, wenn wir ihn flach drücken und anketten wollen? Wollstoff? Wie folgt:

//fn1,f2,f3为处理函数
_if(fn1)._elseIf(fn2)._else(fn3);
Nach dem Login kopieren
Nach dem Login kopieren

Versuchen wir es gemeinsam umzusetzen.

2. Abflachung des Kettencodes

Angenommen, wir haben jetzt den folgenden Kettencode:

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!');
}
Nach dem Login kopieren

Okay, jetzt werden wir ihn Schritt für Schritt abflachen. Wohnung".

Tatsächlich ist es beim Betrachten des obigen Codes nicht schwer festzustellen, dass das if...else-Format tatsächlich eine einfach verknüpfte Liste in der Datenstruktur ist. Verwenden Sie dann zunächst JavaScript, um eine einfach verknüpfte Liste zu implementieren Liste wie folgt:

var thens = [];
thens.resolve = function(name){
    for(var i = 0, len = this.length; i < len;i++){
        if(this[i](name) !== &#39;next&#39;){
            break;
        }
    }
}
thens.push(f1, f2, f3);
Nach dem Login kopieren

Unter diesen sind f1, f2 und f3 Beurteilungsfunktionen, und wir gehen davon aus, dass wir weiter nach unten suchen, wenn f1, f2 und f3 „nächstes“ zurückgeben. andernfalls hören wir auf, nach unten zu suchen. Wie folgt:

function f1(name){
    if(name === &#39;Monkey&#39;){
        console.log(&#39;yes, I am Monkey&#39;);
    }else{
        return &#39;next&#39;;
    }
}
function f2(name){
    if(name === &#39;Dorie&#39;){
        console.log(&#39;yes, I am Dorie&#39;);
    }else{
        return &#39;next&#39;;
    }
}
function f3(){
    console.log(&#39;sorry, over for ending!&#39;);
}
Nach dem Login kopieren

Okay, das ist das Muster der verknüpften Liste.

Allerdings unser oberstes Ziel ist es, Folgendes zu erreichen?

//fn1,f2,f3为处理函数
_if(fn1)._elseIf(fn2)._else(fn3);
Nach dem Login kopieren
Nach dem Login kopieren

Man könnte sagen, wäre es nicht schön, den obigen Code wie folgt zu ändern? ! !

thens.push(f1).push(f2).push(f3).resolve();
Nach dem Login kopieren

Aber Die Push-Methode von JavaScript gibt die neue Länge des Arrays zurück, nicht das Array-Objekt.

Also dann können wir nur eine neue Add-Methode schreiben, die den gleichen Effekt wie Push hat, aber ein Array-Objekt zurückgibt. Wie folgt:

thens.add = function(f){
    if(typeof f === &#39;function&#39;){
        this.push(f);
        return this;        
    }        
}
Nach dem Login kopieren

Der Testcode lautet wie folgt:

var thens = [];
thens.add = function(f){
    if(typeof f === &#39;function&#39;){
        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();
Nach dem Login kopieren

Dies hat jedoch einen Nachteil. Wir binden die Add- und Resolution-Methoden an globale Variable then Sie können die Methode nicht jedes Mal kopieren und einfügen, wenn Sie ein Array erstellen, daher lautet der umgestaltete Code wie folgt:

function Slink(){
    this.thens = [];
    this.thens.add = function(f){
        if(typeof f === &#39;function&#39;){
            this.push(f);
            return this;        
        }        
    }
    this.thens.resolve = function(name){
        for(var i = 0, len = this.length; i < len;i++){
            if(this[i](name) !== &#39;next&#39;){
                break;
            }
        }    
    }
}
Nach dem Login kopieren

Offensichtlich werden öffentliche Methoden wie add und restart jedes Mal verwendet ist instanziiert. Es ist unwissenschaftlich, sie alle zu erstellen. Verwenden Sie daher den Prototyp, um die Verformung auf der ursprünglichen Basis wie folgt fortzusetzen:

function Slink(){
    this.thens = [];
}
Slink.prototype = {
    add: function(f){
            if(typeof f === &#39;function&#39;){
                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) !== &#39;next&#39;){
                    break;
                }
            }    
    }
}
Nach dem Login kopieren

Der Testcode lautet wie folgt:

var thens = new Slink();
thens.add(f1).add(f2).add(f3);
thens.resolve();
Nach dem Login kopieren

Ja, aber in diesem Fall müssen wir jedes Mal manuell einen neuen Slink erstellen, was etwas mühsam ist. Daher kapseln wir den neuen Slink-Prozess wie folgt in eine Funktion :

function $go(f){
    return new Slink(f);
}
function Slink(f){
    this.thens = [];
    this.thens.push(f);
}
Slink.prototype = {
    add: function(f){
            if(typeof f === &#39;function&#39;){
                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) !== &#39;next&#39;){
                    break;
                }
            }    
    }
}
Nach dem Login kopieren

Der Testcode lautet wie folgt:

$go(f1).add(f2).add(f3).resolve();
Nach dem Login kopieren

Okay, Sie sind fertig, jetzt kommt das grammatikalische Zuckerproblem. Der Code ist organisiert wie folgt:

function _if(f){
    return new Slink(f);
}
function Slink(f){
    this.thens = [];
    this.thens.push(f);
}
Slink.prototype = {
    _elseIf: function(f){
            if(typeof f === &#39;function&#39;){
                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) !== &#39;next&#39;){
                    break;
                }
            }
            return this;            
    }
}
Nach dem Login kopieren

Der Testcode lautet wie folgt:

_if(f1)._elseIf(f2)._else(f3).resolve();
Nach dem Login kopieren
Nach dem Login kopieren

Natürlich können Sie zusätzlich zur Verwendung von Arrays auch verwenden Verschlüsseum einen Kettenabflachungseffekt zu erzielen, wie folgt:

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;
    }
}
Nach dem Login kopieren

Der Testcode lautet wie folgt:

function f1(name){
    if(name === &#39;Monkey&#39;){
        console.log(&#39;yes, I am Monkey&#39;);
    }else{
        return &#39;next&#39;;
    }
}
function f2(name){
    if(name === &#39;Dorie&#39;){
        console.log(&#39;yes, I am Dorie&#39;);
    }else{
        return &#39;next&#39;;
    }
}
function f3(){
    console.log(&#39;sorry, over for ending!&#39;);
}
f1._elseIf(f2)._else(f3)('Dorie');
Nach dem Login kopieren

3 Codekette

Was wir oben besprochen haben, sind alle synchrone Prozesse. Wenn Kettenaufrufe vorliegen, gibt es eine asynchrone Situation in der Funktion?

Was bedeutet das? Wie folgt:

function f1(name){
    setTimeout(function(){
        if(name === &#39;Monkey&#39;){
            console.log(&#39;yes, I am Monkey&#39;);
        }else{
            return &#39;next&#39;;
        }
    }, 2000);
}
function f2(name){
    if(name === &#39;Dorie&#39;){
        console.log(&#39;yes, I am Dorie&#39;);
    }else{
        return &#39;next&#39;;
    }
}
function f3(){
    console.log(&#39;sorry, over for ending!&#39;);
}
Nach dem Login kopieren

Wir haben f1 mithilfe von setTimeout asynchron gemacht. Gemäß der Logik des obigen Codes sollten wir warten, bis f1 vollständig ausgeführt wurde (einschließlich der Ausführung von setTimeout), bevor wir entscheiden, ob f2 ausgeführt werden soll ist das wirklich so?

Der Testcode lautet wie folgt:

_if(f1)._elseIf(f2)._else(f3).resolve();
Nach dem Login kopieren
Nach dem Login kopieren

Das Ergebnis der Ausführung des Codes ist, dass nichts ausgegeben wird.

Warum?

Weil JavaScript Single-Threaded ist. Weitere Informationen finden Sie hier.

Wie lässt sich das Problem lösen?

Da es asynchronen Code gibt und die nachfolgende Kette nach dem asynchronen Code verarbeitet werden muss, warten wir auf die Ausführung des asynchronen Codes, bevor wir die nachfolgende Kette wie folgt ausführen:

function f1(name){
    setTimeout(function(){
        if(name === &#39;Monkey&#39;){
            console.log(&#39;yes, I am Monkey&#39;);
        }else{
            //处理后续链
            this.resolve(name, 1);//1代表下一个需处理函数在数组中的位置
        }
    }.bind(this), 2000);
}
Nach dem Login kopieren

Okay, da wir in der Funktion dies verwendet haben, das das Slink-Objekt darstellt, und die Auflösungsmethode geändert haben, müssen wir den Slink-Konstruktor und die Prototypenkette wie folgt optimieren:

function Slink(f){
    this.thens = [];
    this.thens.push(f.bind(this));
}
Slink.prototype = {
    _elseIf: function(f){
            if(typeof f === &#39;function&#39;){
                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) !== &#39;next&#39;){
                    break;
                }
            }
            return this;            
    }
}
Nach dem Login kopieren

The Der Testcode lautet wie folgt:

function f1(name){
    setTimeout(function(){
        if(name === &#39;Monkey&#39;){
            console.log(&#39;yes, I am Monkey&#39;);
        }else{
            //处理后续链
            this.resolve(name, 1);//1代表下一个需处理函数在数组中的位置
        }
    }.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);
Nach dem Login kopieren

Haha, wenn Sie Promise kennen, denken Sie, dass es so ähnlich ist?

Ja, der Zweck ist derselbe, nämlich den Zweck der Reduzierung des asynchronen Codes zu erreichen, aber der Code hier ist viel einfacher als Promise. Einzelheiten zu Promise finden Sie hier.

Das Obige ist die detaillierte Erklärung der Serialisierung der JavaScript-Kettenstruktur. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn).


Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!