Я последнее время практически не бываю на Хабре, зато часто захожу на Reddit. По-моему на последнем гораздо удобнее читать комментарии, в первую очередь потому, что их можно отсортировать по рейтингу и читать только
наиболее «ценные».
Так вот. Сел и написал юзерскрипт, который делает просмотр комментариев на Хабре более удобным.
Комментарии сортируются по рейтингу (в пределах одного уровня).
Ветки комментариев можно сворачивать и разворачивать нажатием на ссылку [-] в заголовке коммента.
Ник автора подсвечивается синим и отмечается буквой [S].
Из этого следует, что глобальные переменные могут затирать свойства window (я уже молчу о том, что они зло, нарушают инкапсуляцию и все такое).
Объявление переменных
При присвоении значения неопределенной локальной переменной используется или создается глобальная переменная.
function foo(){
a =2;
b =3;return a+b;}alert(a);// undefined
a ='очень важное значение';alert(a);// очень важное значение
foo();alert(a);// 2
Таким образом можно легко затереть лишнего. По-моему такое поведение абсолютно нелогично, но, что ж, это не самое странное место яваскрипта. В любом случае неявного определения переменных стоит избегать.
Явно объявлять переменные можно и нужно ключевым словом var.
var a =2;
Такая строка всегда создает новую локальную переменную. Если объявление происходит вне функций, то она будет глобальной, что вполне логично.
function foo(){var a =2;var b =3;return a+b;}alert(a);// undefinedvar a ='очень важное значение';alert(a);// очень важное значение
foo();alert(a);// очень важное значение
Как объявить глобальную переменную из функции? Как обратиться к глобальной переменной, если есть локальная с таким же именем? Очень просто – нужно обратиться к ней как к свойству window:
function foo(){var location ='location';alert(location);// вернет 'location'alert(window.location);// вернет window.location
window.a='переменная из функции';}alert(a);// undefined
foo();alert(a);// переменная из функции
Наследование области видимости
Меня всегда смущало то, что в Javascript можно определять функции внутри функций, а использовать их потом где угодно. Ну да, если посмотреть, точно то же самое можно делать в Ruby, и, наверное, во многих других языках тоже.
Переменные при этом передаются очень просто: если на момент определения функции переменная существовала, то она будет существовать и внутри функции. Откуда бы ее не вызывали.
function alertOnTimeout(message, timeout){return setTimeout(function(){// message будет доступен в безымянной функции, переданной таймаутуalert(message);}, timeout);}
Передача кода по старинке – строкой, которая прогоняется через eval() – не попадает под это правило, код исполняется в той области видимости, где и определен.
Поскольку объекты в Javascript – это тоже типа функции, то свойство объекта определяется точно так же, как и переменная.
function myObject(){var property =0;// Cамо собой, property будет доступно только внутри объекта.}
А еще в Javascript область видимости переменной ограничивается только функциями, а не блоками типа if (привет, Паскаль). Потому удобнее всего объявлять переменные в начале функции.
this
А что this? А то, что эта переменная автоматически появляется в методах объектов и затирает значение this из предыдущей области видимости. Решение простое – переприсваивать ее значение другой переменной.
$('div.with-links').click(function(){var theDiv =this;//сохраняем значение this
$(this).find('a').click(function(){alert($(this).attr('href'));// this - это ссылка
theDiv.remove();// а theDiv - это все еще дивак});});
Отдельно замечу, что при оборачивании какой-то поведенческой логики в объект надо помнить, что в создаваемых DOM-событиях значение this самого объекта теряется.
function myObject(){var _this =this;// сохраняем ссылку на родительский объектvar linkRemoved =false;
$('a').click(function(){
$(this).remove();// this - это объект ссылки
_this.linkRemoved=true;// _this - это родительский объект});}
Решил опубликовать пару скриптов, написанных для lyrified.com.
Итак, растяжка <TEXTAREA> по вертикали. Вообще-то, растяжка любого блочного элемента по вертикали, но применялась именно для текстовых полей.
Проблема: текстовые поля, как правило, или слишком большие, или слишком маленькие. И то, и другое неудобно. Хорошо бы дать возможность изменить высоту поля
Это выглядит вот так:
Тестировалось в IE 6, 7, Firefox 2, 3, Opera 9, Safari 2. читать дальше →