2009-07-08 4 views
16

Я пытаюсь получить принципы выполнения функции jQuery-стиля в моей голове. Под этим я имею в виду:Как работает привязка основных объектов/функций в javascript?

var e = f1('test').f2().f3(); 

У меня есть один пример для работы, а другой нет. Я отправлю их ниже. Я всегда хочу изучить первые принципиальные основы того, как что-то работает, чтобы я мог строить поверх него. До сих пор у меня было только поверхностное и свободное понимание того, как работает цепочка, и я сталкиваюсь с ошибками, которые я не могу устранить.

То, что я знаю:

  1. функции должны возвращать себя, иначе "это вернуть;"
  2. Цепные функции должны находиться в родительской функции, так же как в jQuery, .css() является подходом метода jQuery(), поэтому jQuery(). Css();
  3. Родительская функция должна либо возвращать себя, либо сам новый экземпляр.

Этот пример работал:

var one = function(num){ 
    this.oldnum = num; 

    this.add = function(){ 
     this.oldnum++; 
     return this; 
    } 

    if(this instanceof one){ 
     return this.one;  
    }else{ 
     return new one(num);  
    } 
} 
var test = one(1).add().add(); 

Но это один не делает:

var gmap = function(){ 

    this.add = function(){ 
     alert('add'); 

     return this;  
    } 

    if(this instanceof gmap) { 
     return this.gmap; 
    } else{ 
     return new gmap(); 
    } 

} 
var test = gmap.add(); 
+6

Функции не возвращаются, они возвращают объект, который поддерживает методы, которые вы связываете. В случае jQuery используется узел. – drudru

+1

У каждой функции заканчивается 'return this;'. –

+0

@MarcB - Я знаю, но как? –

ответ

32

В функции JavaScript являются объектами первого класса. Когда вы определяете функцию, это конструктор для этого объекта функции. Другими слова:

var gmap = function() { 
    this.add = function() { 
     alert('add'); 
    return this; 
    } 

    this.del = function() { 
     alert('delete'); 
     return this; 
    } 

    if (this instanceof gmap) { 
     return this.gmap; 
    } else { 
     return new gmap(); 
    } 
} 
var test = new gmap(); 
test.add().del(); 

Назначив

new gmap();
переменного тест, который вы сейчас построили новый объект, который «наследует» все свойства и методы из GMap() конструктора (класс). Если вы запустите фрагмент выше, вы увидите предупреждение для «добавить» и «удалить».

В приведенных выше примерах «это» относится к объекту окна, если вы не обертываете функции другой функцией или объектом.

Цепочка для меня трудно понять сначала, по крайней мере, это было для меня, но как только я понял это, я понял, насколько мощным инструментом это может быть.

4

К сожалению, прямой ответ должен быть «нет». Даже если вы можете переопределить существующие методы (которые вы, вероятно, может во многих UAs, но я подозреваю, может не в IE), вы бы до сих пор застрял с неприятными переименований:

HTMLElement.prototype.setAttribute = function(attr) { 
    HTMLElement.prototype.setAttribute(attr) //uh-oh; 
} 

Лучшее, что вы могли бы, вероятно, уйти с использует другое имя:

HTMLElement.prototype.setAttr = function(attr) { 
    HTMLElement.prototype.setAttribute(attr); 
    return this; 
} 
+0

Похоже, я буду придерживаться jQuery для цепочки! –

+1

Обратите внимание, что этот ответ относится к [другому вопросу] (http://stackoverflow.com/questions/10965781) – kojiro

1

«переписать» функция, но все еще быть в состоянии использовать оригинальную версию, необходимо сначала назначить оригинальную функцию другой переменной. Предположим в качестве примера объекта:

function MyObject() { }; 

MyObject.prototype.func1 = function(a, b) { }; 

Переписать func1 для chainability, сделайте следующее:

MyObject.prototype.std_func1 = MyObject.prototype.func1; 
MyObject.prototype.func1 = function(a, b) { 
    this.std_func1(a, b); 
    return this; 
}; 

Вот working example. Вам просто нужно использовать эту технику на всех стандартных объектах, которые, по вашему мнению, требуют цепочки.

К тому времени, когда вы делаете все эту работу, вы можете понять, что есть более эффективные способы сделать то, что вы пытаетесь сделать, как с помощью библиотеки, которая уже chainability построена в. * кашель * jQuery * cough *

+0

Вот общее решение: http://stackoverflow.com/a/15797662/162793 – sheldonh

-3

Просто вызовите метод как var test = gmap(). add();

, как GMAP функция не является переменной

+0

Это не сработает потому что 'add' не определен в' gmap() ', но только на' new gmap() '. –

0

Во-первых, позвольте мне заявить, что я объясняю своими словами.

Метод цепочки в значительной степени вызывает метод объекта, возвращаемого другой функцией/методом. например (с использованием JQuery):

функция
$('#demo'); 

это JQuery выбирает и возвращает объект JQuery элемент DOM с идентификатором демонстрации. если элемент был текстовым узлом (элементом), мы могли бы привязать метод возвращаемого объекта. например:

$('#demo').text('Some Text'); 

Таким образом, до тех пор, как функция/метод возвращает объект, вы можете цепи метод возвращенного объекта в первоначальное заявление.

Что касается того, почему последние не работают, обратите внимание на то, где и когда используется ключевое слово this. Скорее всего, это проблема контекста. Когда вы вызываете this, убедитесь, что this относится к этому объекту функции, а не к объекту/глобальной области окна.

Надеюсь, что это поможет.