html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Как устроен jQuery: изучаем исходники



jQuery однозначно стал стандартом в индустрии веб-дева. Есть много отличных js-фреймворков, которые заслуживают внимания, но jQuery поразил всех своей лёгкостью, изящностью, магией. Люди пишут с использованием jQuery, люди пишут плагины для jQuery, люди даже пишут статьи про jQuery, но мало кто знает (особенно из новичков), КАК устроен jQuery.

В этой статье проведем небольшой экскурс во внутренности этого фреймворка и разберем, что внутри.
Статья рассчитана на базовые знания Javascript. Задумайтесь и, если вы знаете, как написать клон jQuery, то, скорее всего, вы тут не найдёте ничего нового. Остальным — добро пожаловать под кат


Общие сведения


jQuery — это Javascript-библиотека.


Официальный сайт — jquery.com, автор — John Resig, aka jeresig, известный гуру и бывший евангелист Javascript в Mozilla Corporation. У него есть свой блог — ejohn.org/, где он написал кучу крутых статей и либа для работы с Canvas — processing.js, а также книга «JavaScript. Профессиональные приёмы программирования». Находится в Зале Славы RIT

Основной jQuery-репозиторий располагается на GitHub, где лежат исходники, unit-тесты, сборщик, js-lint проверялка и т.д.

В этот момент я хотел бы сделать отступление и обратить внимание на GitHub. Огромное количество OpenSource Javascript либ — prototype.js, MooTools, node.js, jQuery, Raphael, LibCanvas, YUI а также значительная часть Javascript (и не только Javascript) сообщества нашли приют там, потому, если вы хотите выложить свой javascript-проект, GitHub — лучшее место.

В директории /src находятся исходники, разбитые на множество файлов. Если вы смотрели на файл code.jquery.com/jquery-*.js и ужасались, как там можно не запутаться, то знайте — всё структурировано и не так ужасно. Собираются при помощи билдера на node.js. В нём строки "@VERSION" и "@DATE" исходника заменяются на соответсвующие значения.

Углубляемся в исходники


Coding styles весьма привычные и обычные. Порадую или огорчу вас. Используются табы и египетские скобки. Отбиваются только # indentation, alignment не используется нигде.

Есть два файла — intro.js и outro.js, которые ставятся в начало и конец собранного исходника соответственно.
(function( window, undefined ) {

var document = window.document,
	navigator = window.navigator,
	location = window.location;

	[...] // Основные исходники тут
	
window.jQuery = window.$ = jQuery;
})(window);


Core


Основной интерес для нас представляет файл core.js, в котором и находится всё «мясо».

Исходник выглядит так. Мы видим, что код опустился ещё на один уровень вложенности, что позволяет легче контролировать область видимости переменных:
var jQuery = (function () {
	var jQuery = function ( selector, context ) {
		 return new jQuery.fn.init( selector, context, rootjQuery );
	};
	
	// Map over jQuery in case of overwrite
	_jQuery = window.jQuery,

	// Map over the $ in case of overwrite
	_$ = window.$,

	// A central reference to the root jQuery(document)
	rootjQuery,

	[...]
	
	rootjQuery = jQuery(document);
	
	[...]
	
	return jQuery;
})();


В скопированном участке можно увидеть конструктор jQuery-объекта, сохранённые текущие значения jQuery и $ (понадобятся далее для того, чтобы реализовать jQuery.noConflict()) а также некий rootjQuery — объект jQuery с ссылкой на document ( кеш часто встречаемого $(document), оптимизация )

Чуть ниже — серия RegExp'ов, которые необходимы для реализации jQuery.browser, jQuery.trim, парсинга json и т.п. Современные браузеры подерживают методы ''.trim и [].indexOf, потому jQuery сохранило ссылки на них и использует нативные реализации в своих jQuery.trim и jQuery.inArray.

trim = String.prototype.trim,
indexOf = Array.prototype.indexOf,


Конструирование объекта


Подбираемся к «святая-святых» jQuery — $-функции. Эта часть — самый тяжелый для непривыкшего человека кусок, потому подходим к ней со свежей головой ;) Тут скрыта магия прототипов jQuery, я не буду вдаваться в подробности, почему оно так работает, расскажу только КАК оно работает.

Мы уже видели выше код конструктора jQuery:

var jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
	return new jQuery.fn.init( selector, context, rootjQuery );
},


То есть, при вызове функции jQuery создается и возвращается сущность "jQuery.fn.init". В этом месте используется магия Javascript. Чуть ниже по коду мы можем обнаружить приблизительно следующее:

jQuery.fn = jQuery.prototype = {
	constructor: jQuery,
	init: function( selector, context, rootjQuery ) {
		[...]
	}
	[...]
}

// Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn;


Отныне мы знаем, что jQuery.fn — это ничто иное, как прототип jQuery и это знание поможет нам разобраться кое-с-чем ниже. Также, jQuery.fn.init.prototype указывает на прототип jQuery, и конструктор jQuery.fn.init.prototype указывает на jQuery. Такой подход даёт нам очень интересный результат. Откроем jQuery, консоль Chrome и введем:
$(document) instanceof jQuery; // true
$(document) instanceof jQuery.fn.init; // true


Чтобы вы поняли суть такого поведения, я приведу вам другой пример:
var Init = function () {
	console.log('[Init]');
};

var jQuery = function () {
	console.log('[jQuery]');
	return new Init();
};

Init.prototype = jQuery.prototype = {
	constructor: jQuery
};

var $elem = jQuery(); // [jQuery] , [Init]

console.log( $elem instanceof jQuery ); // true
console.log( $elem instanceof Init   ); // true


Таким образом, всё конструирование находится в функции-объекте jQuery.fn.init, а jQuery — это фабрика объектов jQuery.fn.init

Парсим аргументы


Есть куча вариантов использования функции jQuery:
$(function () { alert('READY!') }); // Функция, которая выполнится только при загрузке DOM
$(document.getElementById('test')); // Ссылка на элемент
$('<div />'); // Создать новый элемент
$('<div />', { title: 'test' }); // Создать новый элемент с атрибутами

// Поддерживает все самые мыслимые и немыслимые css-селекторы:
$('#element'); // Елемент с айди "element"
$('.element', $previous ); // Найти все элементы с классом element в $previous
$("div[name=city]:visible:has(p)"); // И всё, что вы можете подумать

Для детального описания селекторов — читайте статью AntonShevchuk "jQuery для начинающих. Часть 4. Селекторы"

Залезем в конструктор, который, как мы уже знаем jQuery.fn.init. Я приведу здесь псевдокод:
init: function( selector, context, rootjQuery ) {
	if ( !selector ) return this;

	// Handle $(DOMElement)
	if ( selector.nodeType ) return this = selector;

	// The body element only exists once, optimize finding it
	if ( selector === "body" && !context ) return this = document.body;

	if ( jQuery.isFunction( selector ) ) {
		return rootjQuery.ready( selector );
	}

	// Handle HTML strings
	if ( typeof selector === "string" ) {
		// Verify a match, and that no context was specified for #id
		if ( selector.match(quickExpr) ) {
			if ( match[1] ) {
				return createNewDomElement( match[1] );
			} else {
				return getById( match[2] )
			}
		} else {
			return jQuery( context ).find( selector );
		}
	}
},


Первые четыре куска вполне понятны — идет обработка случаев, когда передали пустой селектор, DOM-элемент в качестве селектора или строку 'body' — для более быстрого получения тела документа, а также обработка функции для DomReady.

Интересный момент с случаем, когда мы передаем строку. В первую очередь оно парсит её «быстрым регулярным выражением». В нём левая часть отвечает за нахождение тегов в строке, а вторая — за поиск по айди элемента:
quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/;

И только если запрос более сложный, то вызывается метод find у текущего контекста, который ищет элемент при помощи поискового движка (тоже авторства JResig) Sizzle (права принадлежат The Dojo Foundation).

Разработка плагинов


Многие профессионалы Javascript знают о том, что класс, созданный при помощи прототипов можно очень легко расширять.

var MyClass = function () {
	// constructor
};

MyClass.prototype = {
	// prototype
};

var instance = new MyClass();

// Мы можем расширить прототип класса и новые возможности добавятся во все сущности, даже уже созданные

MyClass.prototype.plugin = function () {
	console.log("He's alive!");
};

instance.plugin(); // He's alive!


Таким же образом мы можем расширять стандартный прототип jQuery:

jQuery.prototype.plugin = function () {
	// Here is my plugin
};


Но, как мы уже заметили выше, fn — это короткая ссылка на jQuery.prototype, потому можно писать короче:

jQuery.fn.plugin = function () {
	// Here is my plugin
	// this здесь ссылается на jquery-объект, от которого вызван метод
};


И данный плагин появится во всех уже созданных и тех, что создадутся сущностях. Добавляя свойства напрямую в объект мы реализуем статические свойства:

jQuery.plugin = function () {
	// Here is my plugin
};


Таким образом, наилучший шаблон для небольших плагинов:

new function (document, $, undefined) {
	
	var privateMethod = function () {
		// private method, used for plugin
	};
	
	$.fn.myPlugin = function () {
		
	};
	
	// и, если нужен метод, не привязанный к dom-элементам:
	$.myPlugin = function () {
		
	};
	
}(document, jQuery);


Именно такой подход можно заметить у большинства плагинов для jQuery, например, DatePicker.

Заключение


На мой взгляд причиной популярности jQuery стала внешняя простота и лёгкость, а также краткость названий: css против setStyles, attr против setAttributes и т.п. Идея была просто прекрасной и покорила умы многих. Очень часто встречаются клоны jQuery или переносятся идеи в другие языки. Но простота обманчива. И не всегда она хороша, так что всегда трижды подумайте, прежде чем сокращать понятное название своего метода, может оно вылезет вам боком ;)

Надеюсь, вам понравилась эта статья и она не оказалась слишком заумной. Если будет желание — можно будет продолжить цикл и углубится в jQuery ещё глубже, или поизучать другие фреймворки.
Читать дальше
Twitter
Одноклассники
Мой Мир

материал с habrahabr.ru

4

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • kop4
          • домен habrahabr.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции