Ограничение области видимости в JavaScript
Иногда в JavaScript нужно создать пару методов которые должны быть видны только изнутри определенного куска кода. Для этого достаточно внести эти методы внутрь анонимной функции и сразу ее выполнить:
(function(){ //наша анонимная функция function func1(){ //первая функция видимость которой нужно ограничить alert('!'); } function func2(){ //вторая функция видимость которой нужно ограничить func1(); } func2(); //внутри блока func1 и func2 "видят" друг друга и могут быть вызваны! })(); //выполнить //при этом вне блока func1 и func2 оказываются невидны!
Этот принцип может быть также использован для создания приватных методов и свойств при программировании объектов.
Корректный способ итерации сквозь объекты
JavaScript удивительно мощный язык и, пожалуй самой мощным его свойством является возможность динамического конструирования объектов. Одной из часто встречающихся задач возникающих при работе с JavaScript является итерация по всем элементам объекта.
Допустим, у нас есть объект созданный вот таким образом:
var obj = {property1:"свойство 1",property2:"свойство 2"};
вот самый распространенный НЕПРАВИЛЬНЫЙ способ показать все свойства объекта:
for(key in obj){ alert(key); }
Вроде все работает правильно и на экране действительно последовательно покажутся все свойства объекта. Почему такой способ является неправильным?
Добавим перед циклом вот такую строчку:
Object.prototype['test1'] = "test1 value";
При запуске скрипта еще раз оказывается, что наш объект волшебным образом приобретает еще одно свойство - test1, хотя мы его не создавали! Это значит что любая сторонняя библиотека которая таким способом расширяет функциональность стандартных классов JavaScript, например prototype.js способна непредсказуем образом изменить логику работы ваших программ. В данном случае хорошим тоном является сравнение текущего свойства и свойства прототипа при каждой итерации, если они равны, значит ничего не делаем:
for(key in obj){ if (obj.constructor.prototype[key]!==obj[key]){ alert(obj[key]); } }
Обратите внимание, что здесь использовано строгое сравнение !==. Все просто, все логично, вот только набирать это каждый раз довольно утомительно, поэтому создадим вот такую функцию:
function forEach(obj,fn){ for(key in obj){ if (obj.constructor.prototype[key]!==obj[key]){ if (fn(key)===false) break; } } }
В этом случае итерация запишется совсем просто:
forEach(obj,function(key){ alert(obj['key']); });
Обратите внимание, что в функции forEach есть возможность остановить итерацию досрочно, что бывает полезно например при поиске элемента, для этого достаточно возвратить false:
forEach(obj,function(key){ alert(obj['key']); if (key=='property1') return false; });
Native in Chrome
Обнаружил что в Google Chrome в JavaScript нельзя создать переменную с именем native - оказывается это ключевое слово зарезервированное на будущее. Интресно что Safari который работает на том же самом движке все работает.
Эмбриопрограммирование
JavaScript это такая штука которая постоянно требует уменьшения размера кода. Чем меньше тем лучше. В идеале программный код должен сам себя распаковывать, дописывать и расширять. Вот такой гомункул получился сегодня
shortEvents:function(names){ x.forEach(names,function(key){ this[names[key]] = new Function("fn","remove","this.on('"+[names[key]]+"',fn,remove)"); },this) },
Кто догадается что это?