Я не могу понять, как работает jQuery Chaining

Я не могу понять, как работает jQuery Chaining.

jQuery("div").attr("id", "_id")
    .hide()
    .show();

Я сделал что-то вроде цепочки, но я не уверен, что это та же логика, которую использует jQuery.

var fun = (function (parma) {
return function () {
    return {
        start: function () {
            console.log("start");
            return this;
        },

        mid: function () {
            console.log("mid");
            return this;
        },

        last: function () {
            console.log("last");
            return this;
        }
    }
}

}) ();

// Working
fun().start()
    .mid()
    .last();

5 ответов

Решение

Если возвращаемое значение функции является объектом, у которого есть метод, вы можете немедленно вызвать этот метод. Просто как тот.

Так как ты возвращаешься this, вы возвращаете тот же объект, к которому был вызван предыдущий метод. Это означает, что вы возвращаете объект всеми одинаковыми методами.


Думайте об этом так:

var f = {
    foo: function() {
             console.log("foo");
             return b;
         }
};

var b = {
    bar: function() {
             console.log("bar");
             return f;
         } 
};

Здесь у нас есть два объекта.

  • f Объект имеет метод с именем foo который возвращает b объект.
  • b Объект имеет метод с именем bar который возвращает f объект.

Из-за этого после звонка fooмы можем позвонить bar, и наоборот.

f.foo().bar().foo().bar(); // etc

Но потому что f не имеет bar а также b не имеет fooмы никогда не сможем вызвать один и тот же метод дважды.


Но что, если бы у нас был только один объект, у которого были оба метода, и оба метода всегда возвращали один и тот же исходный объект?

var fb = {
    foo: function() {
             console.log("foo");
             return fb;
         },
    bar: function() {
             console.log("bar");
             return fb;
         }
};

Теперь мы всегда возвращаем объект, который имеет как foo а также bar методы, поэтому мы можем вызвать любой метод.

fb.foo().bar().bar().bar().foo().foo().bar();

Так что теперь единственная реальная разница в том, что мы возвращаемся fb вместо this, но это не имеет значения, так как они один и тот же объект. Код выше может сделать return this; и он будет вести себя так же.

Было бы важно, если бы вы хотели создать несколько экземпляров объекта, но это вопрос техники ориентации объекта, а не цепочки методов.

return на каждой функции есть объект jQuery. Каждый объект jQuery будет иметь ссылку на все функции, такие как show/hide и так вы можете просто написать

jQuery("#myDiv")         //returns a jQuery object 
    .attr("id", "_id")   //sets the ID and returns the jQuery object
    .hide()              //Hides the element with ID myDiv and returns jQuery object
    .show();             //show the element with ID myDiv and returns jQuery object

Думайте об этом так:

var myLib = {
    foo: function() {
        alert("FOO!");
        return this;
    },
    bar: function() {
        alert("BAR!");
        return this;
    }
}

myLib.foo().bar();

jQuery делает это не совсем так, но это один из способов получить функциональность цепочки. Этот конкретный не хранит информацию о текущем объекте.

У объекта jQuery есть методы, которые возвращают модифицированный объект jquery, что позволяет вам вызывать больше методов для него.

Если я правильно помню, jQuery использует классический подход к созданию цепочки в своих прототипах с одним исключением, он также имеет enhanced Конструктор в это init прототип. Вот простой шаблон:

function myQuery(elem){
   return new myQuery.prototype.init(elem);
};

myQuery.prototype.init = function(elem) { // the constructor "enhanced"
    this.elem = elem;
};

// now copy the myQuery prototypes into init.prototype
myQuery.prototype.init.prototype = myQuery.prototype;

// here comes the chainable prototypes:

myQuery.prototype.start = function() {
    this.elem.className = 'start';
    return this; // returning the instance allows further chaining
};

myQuery.prototype.finish = function() {
    this.elem.className = 'finish';
    return this;
};

// now use it
myQuery(document.body).start().finish();

Цепочка прототипов более эффективна, потому что вы можете повторно использовать методы прототипа для каждого экземпляра. jQuery часто инициализируется много раз в документе, и если вы каждый раз создаете новый объект со всеми цепочечными методами, это добавляет ненужные издержки и возможные утечки.

Почти каждая функция jQuery также будет возвращать объект jQuery. В результате вы можете запускать функции jQuery для каждого возвращаемого объекта.

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

Другие вопросы по тегам