Корректный способ итерации сквозь объекты
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) },
Кто догадается что это?
Почему мне не нравится CodeIgniter
Сегодня потребовалось внести немного изменений в один проект на базе CodeIngniter - это же просто ужасть какой-то - у них нет переменной $_GET, совсем. Сначала я подумал что это бага, ан нет, оказывается, это системная функция, вот что они пишут на этот счет
GET data is simply disallowed by CodeIgniter since the system utilizes URI segments rather than traditional URL query strings (unless you have the query string option enabled in your config file). The global GET array is unset by the Input class during system initialization.
Т.е. пользуйтесь господа разработчики тем что дают и не пользуйтесь тем что есть. т.е. подход такой что CodeIgniter это не система в которой ПОТЕНЦИАЛЬНО можно сделать секюрно, это система в которой ПОТЕНЦИАЛЬНО нельзя сделать несекюрно.
Конечно подход хорош, но мне он не понравился, наверно я до него еще не дорос, или наоборот перерос...
Пришлось передавать данные не через GET а через параметор в адресе, но параметры через адресную строку передаются только буквенно-цифровые - а мне нужно было передать URL для редиректа, поначалу решил закодировать параметр как base64, но как оказалось что base64 оставляет кой какие не-буквенно-цифровые символы, например знаки == на конце текста, иногда. Тогда решил просто заменить все символы их числовыми представлениями в шестнадцатеричной системе - это прокатило.
Cпособ, скорее всего, годится только для строк содержащих только áглицкие буквы если есть неáглицкие может не сработать, но, если не сработает всегда же можно пропустить исходный текст через urlencode.
/** * Этим кодируем */ function an_encode($str){ $result = ''; for($i=0;$i<strlen($str);$i++){ $result .= dechex(ord($str[$i])); } return $result; } /** * Этим декодируем */ function an_decode($str){ $result = ''; for($i=0;$i<strlen($str)/2;$i++){ $result .= chr(hexdec($str[$i*2].$str[$i*2+1])); } return $result; }
Конечно, данные получаются в два раза длинее, но что делать, может кто знает лучший способ?