Что значит jQuery.fn?

Ответы:

848

В jQuery fnсвойство является просто псевдонимом prototypeсвойства.

jQueryИдентификатор (или $) является просто функцией конструкторы , и все экземпляры , созданные с ним, наследуемыми от прототипа конструктора.

Простая функция конструктора:

function Test() {
  this.a = 'a';
}
Test.prototype.b = 'b';

var test = new Test(); 
test.a; // "a", own property
test.b; // "b", inherited property

Простая структура, которая напоминает архитектуру jQuery:

(function() {
  var foo = function(arg) { // core constructor
    // ensure to use the `new` operator
    if (!(this instanceof foo))
      return new foo(arg);
    // store an argument for this example
    this.myArg = arg;
    //..
  };

  // create `fn` alias to `prototype` property
  foo.fn = foo.prototype = {
    init: function () {/*...*/}
    //...
  };

  // expose the library
  window.foo = foo;
})();

// Extension:

foo.fn.myPlugin = function () {
  alert(this.myArg);
  return this; // return `this` for chainability
};

foo("bar").myPlugin(); // alerts "bar"
CMS
источник
4
Это гарантировано, чтобы быть правдой? Могу ли я предположить, что вызов jQuery.prototype точно такой же, как и jQuery.fn? Меня беспокоит, что если jQuery творит чудеса, когда вы звоните .fn, то они не взаимозаменяемы
Брэндон,
4
О, я что-то упускаю .. 'window.foo = foo' дает глобальную область видимости для 'foo'? Я никогда не добавлю это, я добавлю это к моему списку методов, чтобы изучить.
EE33
2
@ EE33 Если я не ошибаюсь, глобальная область видимости в javascript просто означает, что ваша переменная является параметром объекта окна.
Шон
1
@Imray - return thisчтобы разрешить цепочку , чтобы вы могли это сделатьfoo("bar").myPlugin().otherPlugin()
Racing Tadpole
3
@ Думаю, это будет свойство, а не параметр, верно? Параметр будет переменной 'a' здесь function func1 (a) { ... }, а свойство будет переменной 'a' здесь var foo = {}; foo.a = 'a'.
Зак
145

jQuery.fnопределяется как сокращение для jQuery.prototype. Из исходного кода :

jQuery.fn = jQuery.prototype = {
    // ...
}

Это означает jQuery.fn.jqueryпсевдоним для jQuery.prototype.jquery, который возвращает текущую версию jQuery. Опять из исходного кода :

// The current version of jQuery being used
jquery: "@VERSION",
Энди Э
источник
15
Мне нравится этот ответ. Я показываю, как именно найти определение в исходном коде, а затем, как правильно интерпретировать определение. Хороший старый способ научить человека ловить рыбу. +1.
EE33
но какова цель сделать это? просто сохранить пару нажатий клавиш?
Slier
@ Slier: да, в значительной степени.
Энди Э
Могу поспорить, что есть и другая цель ... присоединение функции к $ .fn, сделает статическую функцию
slier
145

fnбуквально относится к JQuery prototype.

Эта строка кода находится в исходном коде:

jQuery.fn = jQuery.prototype = {
 //list of functions available to the jQuery api
}

Но реальным инструментом fnявляется его доступность для подключения вашей собственной функциональности в jQuery. Помните, что jquery будет родительской областью для вашей функции, поэтому thisбудет ссылаться на объект jquery.

$.fn.myExtension = function(){
 var currentjQueryObject = this;
 //work with currentObject
 return this;//you can include this if you would like to support chaining
};

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

jsFiddle Demo

$.fn.blueBorder = function(){
 this.each(function(){
  $(this).css("border","solid blue 2px");
 });
 return this;
};
$.fn.blueText = function(){
 this.each(function(){
  $(this).css("color","blue");
 });
 return this;
};

Теперь вы можете использовать их против такого класса:

$('.blue').blueBorder().blueText();

(Я знаю, что лучше всего это делать с помощью CSS, например, применяя разные имена классов, но имейте в виду, что это просто демонстрация, чтобы показать концепцию)

Этот ответ имеет хороший пример полноценного расширения.

Трэвис Дж
источник
11
Не могли бы вы просто пропустить eachв своем примере кода? $.fn.blueBorder = function(){ this.css("border","solid blue 2px"); return this; };будет работать нормально, так как .css()alerady перебирает элементы.
Скоро
6
@SoonDead - Вы, конечно, могли бы, потому что, если объект jQuery содержит коллекцию, то cssфункция автоматически будет перебирать их внутри каждого из них. Это был просто пример, демонстрирующий различия в том, thisгде внешний является объектом jquery, а внутренний ссылается на сам элемент.
Трэвис Дж
1
@SoonDead Хороший комментарий, но мне действительно нравится, как Трэвис Дж объяснил идею / принцип. :)
Сандер
5
Это лучший комментарий: знать, что fn - это просто псевдоним, не так полезно, как знать, почему кого-то это должно волновать, и этот ответ прекрасно это продемонстрировал.
Джерард ONeill
1
Пройдя через другие ответы, я обнаружил, что этот вопрос легче понять суть концепции. Спасибо. :)
VivekP
0

В исходном коде jQuery, jQuery.fn = jQuery.prototype = {...}поскольку у нас jQuery.prototypeесть объект, значение которого jQuery.fnбудет просто ссылкой на тот же объект, на который jQuery.prototypeуже есть ссылка.

Чтобы подтвердить это, вы можете проверить jQuery.fn === jQuery.prototype, оценивает ли это true(что оно делает), тогда они ссылаются на один и тот же объект

Иегуда Шварц
источник