Ответы:
В 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"
return this
чтобы разрешить цепочку , чтобы вы могли это сделатьfoo("bar").myPlugin().otherPlugin()
function func1 (a) { ... }
, а свойство будет переменной 'a' здесь var foo = {}; foo.a = 'a'
.
jQuery.fn
определяется как сокращение для jQuery.prototype
. Из исходного кода :
jQuery.fn = jQuery.prototype = {
// ...
}
Это означает jQuery.fn.jquery
псевдоним для jQuery.prototype.jquery
, который возвращает текущую версию jQuery. Опять из исходного кода :
// The current version of jQuery being used
jquery: "@VERSION",
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, например, применяя разные имена классов, но имейте в виду, что это просто демонстрация, чтобы показать концепцию)
Этот ответ имеет хороший пример полноценного расширения.
each
в своем примере кода? $.fn.blueBorder = function(){ this.css("border","solid blue 2px"); return this; };
будет работать нормально, так как .css()
alerady перебирает элементы.
css
функция автоматически будет перебирать их внутри каждого из них. Это был просто пример, демонстрирующий различия в том, this
где внешний является объектом jquery, а внутренний ссылается на сам элемент.
В исходном коде jQuery, jQuery.fn = jQuery.prototype = {...}
поскольку у нас jQuery.prototype
есть объект, значение которого jQuery.fn
будет просто ссылкой на тот же объект, на который jQuery.prototype
уже есть ссылка.
Чтобы подтвердить это, вы можете проверить jQuery.fn === jQuery.prototype
, оценивает ли это true
(что оно делает), тогда они ссылаются на один и тот же объект