Поиск…


Цепочка метода

Цепочка метода - это стратегия программирования, которая упрощает ваш код и украшает его. Цепочка метода выполняется путем обеспечения того, чтобы каждый метод объекта возвращал весь объект, вместо того, чтобы возвращать один элемент этого объекта. Например:

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

Обратите внимание, что каждый метод в Door.prototype возвращает this , что относится ко всему экземпляру этого объекта Door .

Цепной дизайн объекта и цепочка

Chaining and Chainable - это методология проектирования, используемая для проектирования поведения объектов, так что вызовы функций объекта возвращают ссылки на себя или другой объект, обеспечивая доступ к дополнительным вызовам функций, позволяющим вызывающему оператору объединять множество вызовов без необходимости ссылаться на переменную, удерживающую объект / с.

Объекты, которые могут быть прикованы, называются цепными. Если вы вызываете объект цепочки, вы должны убедиться, что все возвращенные объекты / примитивы имеют правильный тип. Потребуется один раз, когда ваш объект с цепочкой не вернет правильную ссылку (легко забыть добавить return this ), и человек, использующий ваш API, потеряет доверие и избежит цепочки. Цепные объекты должны быть все или ничего (не цепляемый объект, даже если есть части). Объект нельзя называть цепочки, если только некоторые из его функций.

Объект, предназначенный для соединения

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

Пример цепочки

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

Не создавайте двусмысленность в возвращаемом типе

Не все вызовы функций возвращают полезный цепной тип, и они не всегда возвращают ссылку на себя. Именно здесь важно использование именования в здравом смысле. В приведенном выше примере вызов функции .clone() однозначен. Другие примеры: .toString() подразумевает возврат строки.

Пример неоднозначного имени функции в цепляемом объекте.

 // 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

Соглашение о синтаксисе

При цепочке нет формального синтаксиса использования. Соглашением является либо цепочка вызовов на одну строку, если короткая, либо цепочка на новой строке отступом одна вкладка от объекта, на который ссылается точка с новой точкой. Использование точки с запятой является необязательной, но помогает четко обозначать конец цепи.

  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

Плохой синтаксис

   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

Левая сторона задания

Когда вы назначаете результаты цепочки, назначается последний возвращаемый вызов или ссылка на объект.

 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

В приведенном выше примере vec2 присваивается значение, возвращенное из последнего вызова в цепочке. В этом случае это будет копия vec после масштабирования и добавления.


Резюме

Преимущество изменения - более понятный код. Некоторые люди предпочитают это и будут требовать привязки при выборе API. Существует также преимущество в производительности, так как оно позволяет избежать необходимости создавать переменные для хранения промежуточных результатов. Последнее слово состоит в том, что цельноподобные объекты могут использоваться обычным образом, поэтому вы не применяете цепочку, делая объект целым.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow