Рейтинг
0.00
голосов:
0
avatar

JavaScript  

Для чего нужен jQuery.fn

Каждый кто сталкивался с написанием собственных плагинов на jQuery задавал вопрос — "В чем различие между объявлением функций через jQuery и jQuery.fn?".

Для того, чтобы ответить на поставленный вопрос приведу два примера.

Пример 1.

jQuery.sayHello = function() {
  alert('Привет! Найдено ' + this.length + 'элементов' );
}

$('div').sayHello(); // ничего не происходит


Пример 2.

jQuery.fn.sayHello = function() {
  alert('Привет! Найдено ' + this.length + 'элементов' );
}

$('div').sayHello(); // Выводит "Привет! найдено ХХ элементов", где ХХ - это количество найденных элементов на странице


Если запустить первый пример, то произойдет одно из двух событий — браузер выдаст ошибку (например, если у Вас установлен FireBug) либо не выдаст ничего. А если запустить второй пример, то на экране появится сообщение о количестве найденных элементов.

Прежде чем делать какие-либо выводы, приведу еще один пример:


jQuery.sayHello = function(elem) {
  alert('Привет! Найдено ' + elem.length + 'элементов' );
}

jQuery.sayHello($('div'));


В данном примере, будет выдано сообщение о количестве найденных объектов.

Думаю теперь у нас достаточно информации, чтобы сделать некоторые выводы:

Вывод 1: Если задать функцию через jQuery.fn, то она будет работать с элементами найденными через функцию $(). Контекст этой функции будет содержать выбранные элементы;

Вывод 2: Если задать функцию через jQuery, то к ней можно обратиться только через глобальный объект jQuery. В таком случае контекст функции будет указывать на глобальный объект window.

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

Как быстро проверить число на NaN

Сегодня копался в коде jQuery и обратил внимание на то каким образом осуществляется проверка числа на NaN. Вместо того, чтобы использовать стандартную функцию isNaN() Johng Resig преобразует число к строке и сравнивает его со строкой 'NaN'.

Я подумал, что раз используется такой странный способ, то тому есть свое логическое объяснение. Первое, что пришло мне на ум — выигрыш в скорости, но как оказалось это совершенно не так.


Для проверки я написал простенький скрипт:


function a() {
	for (var i = 0; i < 100000; i++) {
		var n = parseInt('AAAA');
		isNaN(n); // true
	}
}

function b() {
	for (var i = 0; i < 100000; i++) {
		var n = parseInt('AAAA');
		'NaN' == n.toString() ; // true
	}
}

a();
b();


Чтобы не заморачиваться на измерение скорости средствами JavaScript использовал профилирование встроенное в плагин FireBug.

После проведение замеров FireBug показал следующее:
функция b() — 32 мс
функция a() -13 мс.


Получается, что isNaN работает быстрее более чем в два раза!

Ради справедливости стоит отметить, что в других браузерах результаты могут быть иными, возможно даже в более старой версии FireFox-а выигрыш будет на стороне toString(). Но в FireFox 3.6 ситуация такая как я описал выше.

Если кто-то может привести данные о времени работы аналогичного кода для Оперы и IE милости прошу отписаться в комментариях.

Из сказанного выше, можно сделать вывод, что для работы в FireFox лучше использовать функцию isNaN. Но значит ли, что не существует другого более быстрого способа проверить число на NaN?

Чтобы ответить на данный вопрос, я решил провести еще пару экспериментов.

Первое, что пришло мне на ум — это изменить способ перевода числа в строку, для этого я заменил код n.toString() == 'NaN' на n + '' === 'NaN'; в результате функция b(); стала выполняться на 5мс быстрее. Но функция isNaN() все равно работала значительно лучше.

Второе решение, я нашел в интернете и заключается оно в том, чтобы проверить равно ли число само себе, а точнее не равно ли оно само себе:

var n = parseInt('AAAA');
n != n // true 


Я уже писал об особенностях числа NaN одно из которых заключается в том, что NaN не равно самому себе, таким образом сравнение n != n будет истинным только в случае когда n равно NaN.

Чтобы проверить указанный метод. Я заменил проверку toString() на n != n и запустил профилирование повторно. В результате были получены следующие значения:

функция a() — 13 мс
функция b() — 8 мс (!)


Таким образом, на сегодняшний день самый быстрый способ (известный мне) проверить число на значение NaN — это выполнить проверку n != n.

JavaScript. Грабли с NaN

Программируя на javascript никогда не знаешь когда встанешь на очередную граблю. Иногда складывается впечатление, что в языке больше плохого чем, хорошего.

Например, в JS есть такое значение — NaN расшифровывается как Not A Number. Обычно это значение возвращается при ошибке выполнения операций с числами.


parseInt('AAAA'); // NaN
parseInt('1'); // 1
parseInt('16 somthing else'); // 16 — неожиданно, правда?


В данном примере, при выполнении первой операции функция parseInt не смогла преобразовать строку в число и поэтому вернула значения NaN. А вот в 3-ей строке, все прошло успешно, что кажется мне не совсем логичным.

Другие фокусы, которые выкидывает JavaScript хорошо демонстрирует следующий пример:


NaN == NaN; // false
NaN != NaN; // true
NaN > NaN; // false
NaN < NaN; // false

typeof NaN === 'number';  // true


Получается, что NaN не равен сам себе, одновременно NaN не больше и не меньше самого себя. А если запросить его тип, то оказывается, что это число. Непонятно, почему тогда не работают операции сравнения.

Плохо в данной ситуации то, что код который многим кажется вполне рабочим, на самом деле таковым не является:



function sum(a, b) {
	a = parseInt(a, 10);
	b = parseInt(b, 10);
	if (a == NaN || b == NaN) {
		alert('Ошибка');
		return 0; 
	}
	return a+b;
}

sum('1', 'bbbb');  // NaN



Причина, в том, что сравнение a == NaN || b == NaN — всегда будет возвращать false, даже если a или b будут иметь значение NaN.

Для того, чтобы узнать содержит ли переменная значение NaN используется функция isNaN:


isNaN(NaN); // true
isNaN('AAAA'); // true
isNaN('0'); // false


Чтобы избежать проблем со значением NaN я использую собственную функцию определения является ли переменная числом:


function isNum(v) {
	return typeof v === 'number' && isFinite(v);
}
  • 0
  • 28 января 2010, 06:04
  • admin
  • 1+1

Подводные камни JavaScript или опасное свойство Semicolon insertion.

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

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


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

var a
var b

Во время выполнения он будет преобразован к следующем виду:

var a;
var b;


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

Для примера возьмем следующий код:

function a() {
return 
	false;
}

Не трудно догадаться, что в данной ситуации программист хотел чтобы функция возвращала значение «false». Но на самом деле она возвращает значение «undefined». И это вполне закономерно, потому что реально исполняется совсем другой код:

function a() {
return ; // Обратите внимание JS сам доставил «недостающий» знак точки с запятой
	false;
}

Самое простое, что можно сделать для избежания проблем с Semicolon insertion — это не разрывать строки на две подстроки. Но и этого будет недостаточно, для написания абсолютно безопасного кода.

Синтаксис JavaScript очень похож на синтаксис языка «Си». Например, для выделения блоков когда в JS как и в «Си» используются фигурные скобки.

Обычно программисты предпочитают один из двух вариантов оформления.

Первый — это когда открывающая фигурная скобка находится на одном уровне с конструкцией к конторой она относится:
function a() {
	return {
		value: false
	}
}

Второй — когда открывающую скобку помещают на уровень ниже

function a() 
{
	return 
	{
		value: false
	}
}

Не трудно догадаться, что для JavaScript второй вариант пригоден не во всех случаях, в примере выше во время выполнения будет получен следующий код:

function a() 
{
	return ;
	value: 
		false;
}

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

Конечно, сказанное выше описывает далеко не все возможные ситуации когда Semicolon insertion вызовет проблемы при выполнении кода. Поэтому я приглашаю всех дополнить эту статью своими примерами и мыслями используя для этого комментарии.
  • 0
  • 25 января 2010, 07:19
  • admin
  • 1+1
Рублёвый Форекс: теперь и в МТ4 - форекс счет. Технический анализ бесполезен. . Магазины мебели