Szukaj…


Łączenie metod

Łańcuch metod to strategia programowania, która upraszcza kod i upiększa go. Tworzenie łańcuchów metod odbywa się poprzez upewnienie się, że każda metoda na obiekcie zwraca cały obiekt, zamiast zwracać pojedynczy element tego obiektu. Na przykład:

function Door() {
    this.height = '';
    this.width = '';
    this.status = 'closed';
}

Door.prototype.open = function() {
    this.status = 'opened';
    return this;
}

Door.prototype.close = function() {
    this.status = 'closed';
    return this;
}
Door.prototype.setParams = function(width,height) {
    this.width = width;
    this.height = height;
    return this;
}

Door.prototype.doorStatus = function() {
    console.log('The',this.width,'x',this.height,'Door is',this.status);
    return this;
}

var smallDoor = new Door();
smallDoor.setParams(20,100).open().doorStatus().close().doorStatus();

Zauważ, że każda metoda w Door.prototype zwraca this , co odnosi się do całej instancji tego obiektu Door .

Projektowanie i łańcuchowanie obiektów łańcuchowych

Łańcuchowe i łańcuchowe to metodologia projektowania stosowana do projektowania zachowań obiektowych, dzięki czemu wywołania funkcji obiektowych zwracają odwołania do siebie lub innego obiektu, zapewniając dostęp do dodatkowych wywołań funkcji, umożliwiając łączenie wielu wywołań instrukcji wywołującej bez potrzeby odwoływania się do trzymania zmiennej obiekt / y.

Obiekty, które można powiązać, są łańcuchowe. Jeśli nazywasz obiekt łańcuchem, powinieneś upewnić się, że wszystkie zwracane obiekty / operacje podstawowe są poprawnego typu. Wystarczy tylko jeden raz, aby obiekt łańcuchowy nie zwrócił poprawnego odwołania (łatwo zapomnieć o dodaniu return this ), a osoba korzystająca z interfejsu API straci zaufanie i uniknie tworzenia łańcuchów. Przedmioty łańcuchowe powinny być wszystkim lub niczym (nie łańcuchem, nawet jeśli części są). Obiekt nie powinien być nazywany łańcuchem, jeśli są tylko niektóre jego funkcje.

Obiekt zaprojektowany jako łańcuchowy

function Vec(x = 0, y = 0){
    this.x = x;
    this.y = y;
    // the new keyword implicitly implies the return type 
    // as this and thus is chainable by default.
}
Vec.prototype = {
    add : function(vec){
        this.x += vec.x;
        this.y += vec.y;
        return this; // return reference to self to allow chaining of function calls
    },
    scale : function(val){
        this.x *= val;
        this.y *= val;
        return this; //  return reference to self to allow chaining of function calls
    },
    log :function(val){
        console.log(this.x + ' : ' + this.y);
        return this;
    },
    clone : function(){
        return new Vec(this.x,this.y);
    }
}

Przykładowy łańcuch

var vec = new Vec();
vec.add({x:10,y:10})
    .add({x:10,y:10})
    .log()             // console output "20 : 20"
    .add({x:10,y:10})
    .scale(1/30)
    .log()             // console output "1 : 1"
    .clone()           // returns a new instance of the object
    .scale(2)          // from which you can continue chaining
    .log()

Nie twórz dwuznaczności w typie zwrotu

Nie wszystkie wywołania funkcji zwracają przydatny typ łańcuchowy, ani nie zawsze zwracają odniesienie do siebie. W tym przypadku ważne jest stosowanie nazewnictwa opartego na rozsądku. W powyższym przykładzie wywołanie funkcji .clone() jest jednoznaczne. Inne przykłady to .toString() oznacza, że zwracany jest ciąg znaków.

Przykład niejednoznacznej nazwy funkcji w obiekcie łańcuchowym.

 // line object represents a line
 line.rotate(1)
    .vec();  // ambiguous you don't need to be looking up docs while writing.

 line.rotate(1)
    .asVec()    // unambiguous implies the return type is the line as a vec (vector)
    .add({x:10,y:10)
 // toVec is just as good as long as the programmer can use the naming 
 // to infer the return type

Konwencja składniowa

Podczas tworzenia łańcuchów nie ma formalnej składni użycia. Konwencja polega na łączeniu połączeń na jednej linii, jeśli jest krótka, lub na nowej linii, wcięcie jednej zakładki od obiektu odniesienia za pomocą kropki na nowej linii. Użycie średnika jest opcjonalne, ale pomaga w wyraźnym oznaczeniu końca łańcucha.

  vec.scale(2).add({x:2,y:2}).log();  // for short chains

  vec.scale(2)     // or alternate syntax
      .add({x:2,y:2})
      .log();  // semicolon makes it clear the chain ends here

  // and sometimes though not necessary
  vec.scale(2)     
      .add({x:2,y:2})
      .clone()    // clone adds a new reference to the chain
           .log(); // indenting to signify the new reference

  // for chains in chains
  vec.scale(2)     
      .add({x:2,y:2})
      .add(vec1.add({x:2,y:2})  // a chain as an argument 
           .add({x:2,y:2})      // is indented
           .scale(2))
      .log();

  // or sometimes 
  vec.scale(2)     
      .add({x:2,y:2})
      .add(vec1.add({x:2,y:2})  // a chain as an argument 
           .add({x:2,y:2})      // is indented
           .scale(2)
      ).log();   // the argument list is closed on the new line

Zła składnia

   vec          // new line before the first function call
      .scale()  // can make it unclear what the intention is
      .log();

   vec.          // the dot on the end of the line
      scale(2).  // is very difficult to see in a mass of code
      scale(1/2); // and will likely frustrate as can easily be missed
                  // when trying to locate bugs

Lewa strona zadania

Po przypisaniu wyników łańcucha przypisywane jest ostatnie wywołanie zwrotne lub odwołanie do obiektu.

 var vec2 = vec.scale(2)
                .add(x:1,y:10)
                .clone();   // the last returned result is assigned
                                // vec2 is a clone of vec after the scale and add

W powyższym przykładzie vec2 jest przypisana wartość zwrócona z ostatniego wywołania w łańcuchu. W tym przypadku byłaby to kopia vec po skalowaniu i dodaniu.


streszczenie

Zaletą zmiany jest wyraźniejszy, łatwiejszy w utrzymaniu kod. Niektóre osoby wolą to i przy wyborze interfejsu API będą wymagały tworzenia łańcuchów. Istnieje również korzyść z wydajności, ponieważ pozwala uniknąć konieczności tworzenia zmiennych w celu przechowywania wyników pośrednich. Ostatnim słowem jest to, że obiekty łańcuchowe mogą być również używane w konwencjonalny sposób, więc nie wymuszaj tworzenia łańcuchów, czyniąc obiekt łańcuchem.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow