Открыть меню    

Тайна объекта jQuery: основы для понимания

базовая информация по объекту jQuery Когда-нибудь мы все натыкались на кусок кода Javascript вида $('.cta').click( function(){ } ) и думали: «Что за $('#x')»? Если для вас это также выглядит странно и непонятно, читайте дальше. Если вы думаете, что данный код не может быть реальным, пожалуйста, просмотрите примеры jQuery. Они полны таких конструкций.

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

jQuery

$(document).ready(function(){
    $("button").click(function(){
        $("div").animate({height:"toggle"}).append("hi");
    });
});

Мы пройдемся по каждому слову в коде выше, детально разберем javascript функции, jQuery объект и событийно-ориентированное программирование. В конце концов, надеюсь, вам не придется больше впадать в ступор от приведенного выше кода.

Что такое $?

На первый взгляд знак доллара $ выглядит чем-то особенным, частью Javascript функциональности. Это не так. Знак доллара не является специальным символом Javascript. На самом деле $ это просто функция. Это альтернативное имя для функции jQuery.

И функция jQuery является причиной популярности библиотеки jQuery. JQuery это компактная javascript библиотека, которая сглаживает много раздражающих различий между браузерами и обеспечивает много полезных особенностей для манипулирования (плюс анимация) над элементами веб-страницы. Вы можете подключить функцию jQuery (то есть $) к вашей странице посредством ссылки на библиотеку:

HTML

<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>

Как вариант, вы можете скачать библиотеку на сайте jQuery и положить ее туда куда захотите:

скачать библиотеку jQuery

jQuery принимает обычно один аргумент, либо селектор или Javascript ссылку на что-нибудь на странице, например, document.

Селектор является частью CSS, то есть та часть, что стоит перед {...}. Так, $('div') равнозначна конструкции jQuery('div') и такое поведение очень грубо схоже со следующим CSS, где происходит выборка всех div элементов на текущей странице:

<style>
    div {...}
</style>

Вернемся к началу нашего примера, $(document) передает javascript переменную document в функцию jQuery. Переменная document устанавливается браузером автоматически. Она ссылается на объектную модель документа (DOM). Функциональность jQuery построена на анализе всего HTML страницы посредством DOM. Например, в jQuery $('div') делает примерно тоже самое, что и document.getElementsByTagName("div").

Примечание

Помните, что $ это просто функция, альтернативное и более удобное имя для функции jQuery.

Точка

Знак . , который идет после $(document) означает богатство функциональных возможностей. Точка используется с объектами JavaScript. JavaScript объект является коллекцией свойств. Например:

Javascript

var digger = new Object();
digger.species = "gerbil";
digger.name = "Digger";
digger.color = "white";

В этом примере переменная diger является объектом, мы привязали к ней три подпеременные (свойства): species, name и color. В объектно-ориентированном жаргоне они известны как переменные членов (или свойства). Все приведенное выше можно записать более кратко, например:

Javascript

var digger = {species:"gerbil", name:"Digger", color:"white"};

Вы также можете определить функцию как свойство объекта. Песчанки (gerbil) в общем-то тихие грызуны, но иногда они могут издавать пронзительный звук. В JavaScript это может выглядеть следующим образом:

Javascript

function meepMeep(){
    alert("meep meep");
}

В JavaScript границы между переменными, функциями и объектами весьма размыты. Таким образом функция может быть легко присвоена переменной (члену/св-ву):

digger.speak = meepMeep;

Вы можете вызвать эту функцию и песчанка заговорит:

digger.speak();

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

Javascript

function myNameIs(){
    alert("Meep! I am a " + this.species);
}
//присваиваем функцию
digger.sayMyName = myNameIs;
//вызываем функцию
digger.sayMyName();

В функции myNameIs специальная переменная this ссылается на текущий (охватывающий) объект; конструкция this.species равнозначна digger.species и имеет значение gerbil (песчанка). Если вы попытаетесь вызвать myNameIs() напрямую, без объекта, тогда this будет ссылаться на объект javascript window и this.species стало быть станет равнозначна переменной window.species, которая равна undefined. Страницы бы вывела: "Meep! I am a undefined." (отметьте, что функции в js передаются по ссылке).

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

Javascript

function giveMeTheGerbil(){
    return digger;
}

Эта функция вернет ссылку на глобальную переменную или объект digger, с которым вы можете работать точно также, как и с оригинальным объектом digger.

Javascript

var digger2 = giveMeTheGerbil();
//alerts "Meep! I am a gerbil"
digger2.sayMyName();

Тем не менее вы можете пропустить переменную-посредник и просто вызвать sayMyName непосредственно на возвращаемое значение от giveMeTheGerbil:

giveMeTheGerbil().sayMyName();

Без внутреннего кода, однако это та же самая структура, что и у нашего оригинального примера:

$(document).ready(...);

Следующий раздел описывает, что на самом деле делает ready.

Ключевой момент

Литеральная (сокращенная) нотация для объекта выглядит следующим образом: {name:"Digger", species:"gerbil"}.

Ключевое слово this используется в функции присоединенной к объекту (метод) и ссылается на текущий (охватывающий) объект.
ИЛИ: Параметр this ссылается на объект, который неявно связан с вызываемой функцией и называется контекстом вызова.

Анонимные функции

В Javascript есть несколько способов создать функцию. Ниже приведен классический способ (Function Declaration), который должен быть знаком любому программисту.

function meepMeep(){
    alert("meep meep");
}

Выше мы видели, что функции могут быть присвоены переменным. Мы создали функцию meepMeep и присвоили ее digger.speak. Фактически функция может быть создана анонимно (Function Expression), то есть вообще без имени, и затем такую функцию можно присвоить переменной:

var meepMeep = function(){
    alert("meep meep");
};

В javascript функции могут быть присвоены переменным и переданы в функцию подобно переменным. Например:

function runMe(f){
    f();
}

Функция имеет один аргумент f. Функция runMe рассматривает этот аргумент как функцию и вызывает ее. Таким образом, вы могли бы написать так:

runMe(meepMeep);

Это становится еще более интересным, когда у функции вообще нет официального имени meepMeep. Функцию при необходимости можно сразу создать и передать непосредственно в runMe:

runMe(function(){
    alert("meep meep");
});

Фактически meepMeep может появиться в любом месте, но что насчет анонимного эквивалента. Например для этой функции:

meepMeep();

Вместо этого мы могли бы на место meepMeep поставить анонимную функцию, окружив ее предварительно дополнительными скобками (это немедленно вызываемая функция).

(function(){
    alert("meep meep");
})();

Эта техника часто используется, чтобы создать локальную область видимости в Javascript. Что будет делать нижеприведенный код?

var x=3;
(function(){
    var x=4; console.log("x is " + x);
})();
console.log ("x is " + x);

Ключевой слово var внутри функции играет важную роль. Оно объявляет переменную внутри функции. В анонимной функции определена своя локальная переменная x, которой присвоено значение 4, и затем происходит ее вывод. Из-за ключевого слова var, x внутри функции полностью отделена от предыдущего кода (var x=3). Таким образом этот код сначала выведет x is 4 и затем x is 3.

Так как наша песчанка больше не издает пронзительного писка, код выше использует console.log для вывода результата, а не alert. console.log реализован в современных браузерах (другими словами, не в старых IE) и выводит ненавязчиво в браузере (консоли) ошибки, сообщения и т.д..

Анонимные функции следующий кусок головоломки. Метод jQuery ready подобен функции выше runMe, но с временной задержкой. Метод ready ждет, когда DOM полностью загрузится и затем запускает предусмотренную функцию. Итак, когда document наконец-то ready, следующая анонимная функция будет запущена:

function(){
    $("button").click (...)
}

$(document).ready(...) является распространенным способом для программистов выполнить какой-либо код JavaScript только после того как весь HTML документ будет обработан.

Ключевой момент

Анонимные функции являются функциями без имени, например, function(){ alert(1); }. Они могут назначаться переменным, передаваться в другие функции или запускаться сразу, чтобы создать локальную область видимости.

Связывание (цепочка) методов

Прежде чем погрузиться в код, нам требуется рассмотреть еще одну концепцию, которая часто встречается в javascript. Метод цепочка основан на запуске функций стоящих в одном в ряду. На самом деле это просто расширение giveMeTheGerbil() из кода выше:

giveMeTheGerbil().sayMyName();

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

digger.speak = function(){
    alert("meep meep"); return this;
}
digger.sayMyName = function(){
    alert("Meep! I am a " + this.species); return this;
}

Сейчас эти две функции что-то делают с digger (копалка) и затем возвращают digger. Нет больших отличий, но немного измененный код позволяет нам строить из функций цепочку (сцепить функции вместе).

giveMeTheGerbil().speak().sayMyName().speak();

Эта строка кода будет сперва запускать giveMeTheGerbil, возвращать ссылку на объект digger. Сейчас наш код эквивалентен следующей записи:

digger.speak().sayMyName().speak();

Затем будет вызван метод speak объекта digger и выведено предупреждение meep meep. Здесь также возвращается ссылка на digger, при этом код станет эквивалентен следующему:

digger.sayMyName().speak();

После этого будет вызвана ф-я sayMyName и снова возвращена ссылка на digger. Все эти действия приведут к 3 предупреждениям: meep meep, Meep! I am a gerbil, meep meep.

Такого рода цепочки часто встречаются в JavaScript. Вы можете увидеть их у строковых (string) объектов.

Javascript

var s = "I have a dagger.";
console.log(s.substring(9, 15).replace("a", "i").toUpperCase());

Код выше инициализирует строку (s), извлекает подстроку, заменяет букву «a» на «i», приводит результирующее слово к верхнему регистру и возвращает результирующую строку, которая выводится в консоли.

Конечно, цепочки встречаются в jQuery повсюду и появятся и в нашем примере:

jQuery

$("div").animate({height:"toggle"}).append("hi");

$("div") ищет все div элементы страницы и возвращает их как часть jQuery объекта. Он запускает animate метод объекта jQuery и затем запускает append, при этом каждый раз возвращается и эксплуатируется объект jQuery.

Эти цепочки могут получиться довольно длинными. Ниже в частности приведен гордый пост о наличии у пользователь длинной цепочки:

Стоит сказать, что длинные цепочки тяжело отлаживать и поддерживать. Таким образом избегайте составление длинных цепей, но короткая цепь может быть весьма полезна.

Ключевой момент

Функции относящиеся к объектам, то есть методы, которые возвращают ссылки на себя (то есть «выбранные элементы» или объект jQuery) могут быть соединены друг с другом, позволяя выполнить много кода без сохранения промежуточных результатов.

Объект jQuery

Наш пример использует несколько методов jQuery: ready, click, animate и append. Все эти функции присоединены к объекту jQuery подобно тому, как функции speak и muNameIs присоединены к объекту digger или как substr, replace и toUpperCase к строкам.

Все эти функции являются методами объекта jQuery и они все возвращают объект jQuery. Внутри, однако, объект jQuery является более сложным, чем diger или string.

Как уже упоминалось ранее, барьеры между концепциями в JavaScript могут быть расплывчатыми. Объект jQuery ведет себя как объект и как массив. В цепочке методов вы рассматриваете его как объект, но вы можете рассматривать его и как массив:

var mydivs = $("div");
for (var i = 0; i < mydivs.length; i++)
{
    console.log(mydivs[i].innerHTML);
}

В этом примере $('div') ищет все div элементы на странице и сохраняет результирующий jQuery объект в переменной mydivs. Код проходит через jQuery объект как если бы это был массив nodes (узлы; фактически, NodeList) в DOM. Эти узлы также являются объектами с их собственными (нативными) свойствами, такими как outerHTML и innerHTML.

Достигнуть такой же результат, но при помощи jQuery, можно путем возврата этих узлов в jQuery объекты, после чего можно вызвать метод jQuery, например, html. Чтобы сделать это, просто передайте эти узлы в функцию jQuery ($), которая превращает почти все в объект jQuery.

var mydivs = $("div");
for (var i = 0; i < mydivs.length; i++)
{
    console.log($(mydivs[i]).html());
}

Здесь мы два раза выведем HTML содержимое каждого div страницы.

Обратите внимание, когда вы запускаете кусок кода jQuery, например, $("div").animate(...).append(...); анимация срабатывает на все div элементы в jQuery объекте, и они все передаются следующей функции в цепочке, как часть jQuery объекта (Это верно для большинства, но не всех функций jQuery).

Ключевой момент

jQuery функция $ и большинство jQuery методов, например, такие как click и animate возвращают jQuery объект, который является частично объектом и частично массивом. Массивная часть содержит ссылки на узлы DOM.

Собираем все вместе

Теперь мы можем посмотреть на весь пример в целом. $(document) возвращает jQuery объект, который ссылается на саму страницу. В ready( ) передается функция, которая запускается, когда страница полностью обработана и DOM полностью доступен.

function(){
    $("button").click(…);
}

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

function(){
    $("div").animate ({ height:"toggle" }).append("hi");
}

Эта функция ищет все элементы div, возвращает jQuery объект, и вызывает его метод animate. Аргументом метода animate является список свойств, которые передаются в качестве литерала объекта { height:"toggle" }. Это говорит jQuery, что нужно переключить высоту всех div элементов на странице из одного состояния в другое. Сперва это сделает высоту всех элементов равной 0. В следующий раз, элементы плавно вернут свою прежнюю высоту.

Метод animate также возвращает jQuery объект. Для этого объекта вызывается метод append (реализованный при помощи цепочки методов), который добавляет строку 'hi' каждому div, но при условии клика по кнопке. Вставьте это в HTML страницу или в JS Bin, чтобы увидеть код в действии.

<button>Click me</button>
<div style="width:100px;height:100px;background:green;"></div>
<script src="http://code.jquery.com/jquery-1.8.3.js"></script>
<script>
$(document).ready(function(){
    $("button").click(function(){
        $("div").animate({height:"toggle"}).append("hi");
    });
});
</script>

Каждый раз при клике по кнопке, зеленый div сворачивается или разворачивается и получает строку 'hi' (добавляется внутрь div). Этот код прост, тем не менее он хорош для понимания основных принципов работы jQuery.

Событийно-управляемые проблемы

Этот фрагмент выглядит вполне невинно:

//установили h значение 200
var h = 200;
$(document).ready(function(){
    $("button").click(function(){
        //animate up to h, 200 pixels high
        $("div").animate({height:h});
    });
});

Вы ожидаете, что div увеличится до 200px. Однако на момент присваивания переменной h значения и запуском анимации произойти могло многое. В составе jQuery приложения переменная h может уже использоваться или в другой части вашего приложения у переменной может быть изменено значение. И вы будете внимательно вглядываться в эти несколько строк кода, размышляя о том, почему ваш блок имеет высоту 50px вместо 200. Это потому, что где-то в вашем коде, вы, вероятно, имеете for <p>(h=1; h<50; h++) {...}</> , что поменяло значение переменной h.

Справедливости ради стоит сказать, что эта проблема не обусловлена jQuery или анонимными функциями, эта опасность событийного программирования в целом. Строки выше запускаются в 3 разных временных промежутка: когда они проработаны ($(document).ready(...)), когда документ загружен ($("button").click(...)) и когда произведен клик по кнопке ($("div").animate(...)).

Серверный код, написанный, например, на таких языках как PHP, работает последовательно и в порядке от начала и до конца, выводя HTML страницы и затем завершается. JavaScript может делать тоже самое, но его мощь в использовании событий, таких, например, как клик по кнопке. Это и есть событийное программирование, и это не только JavaScript (Objective-C, Java, С++).

Если код выше перевести на Java и запустить на мобильном телефоне, то ссылка на h во внутренней функции вызовет ошибку. Это потому, что переменная h не была объявлена как глобальная (или static в Java) и таким образом код внутри функции не знает какое значение есть у переменной. Это не решает проблемы, но по крайней мере вы задумаетесь о том, как использовать переменные.

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

$(document).ready (function(){
    //set h to 200
    var h = 200;
    $("button").click (function(){
        //animate up to h, 200 pixels high
        $("div").animate ({height:h});
    });
});

Если необходимо использовать глобальную переменную, то вы можете использовать иную технику, например, правильно именовать и группировать переменные. Рекомендуется также всегда комментировать свой код.

//properties of the animation
var animationConfig = {upToHeight:200};
//when document is loaded
$(document).ready(function(){
    //when any <button> element is clicked
    $("button").click(function(){
        //change the height of all <div>s
        $("div").animate({height:animationConfig.upToHeight});
    });
});

Заключение

Это статья является руководством для начинающих о синтаксисе JavaScript и jQuery. Jquery это просто JavaScript библиотека, которая имеет особенную функцию $, и поощряет использование литералов объектов, анонимные функции и цепочки методов. Jquery не одинок - библиотека YUI (Yahoo User Interface ) делает похожие вещи.

Теперь вы можете посмотреть на часть кода jQuery без смущения. Вы знаете, что он делает. Из-за сложной событийного программирования вы, возможно, не уверены когда, но вы знаете как.

источник

Комментарии к статье

аватарка пользователя
2015-01-12
Денис

Спасибо за статью!
Вы пропустили букву "g" в предложении "В этом примере переменная diger …" после фотки мыши.

аватарка пользователя
2017-03-24
Summersid

Отличная статья! Мое понимание стало глубже ,)