Полемика о Object, Array, for..in, prototype... Большая и скучная проблемма
Мне не удалось найти какого нибуть хорошего решения для данной проблеммы.
Вот в чём её суть:
Допустим нам нужно расширть возможности стандартного "класса" Array.
Например функция max.
И тут у нас есть 2 варианта:
- Сделать это в "стиле javascript"
- Сделать это в "стиле PHP"
Выбирающие первый вариант могут написать такой простенький и красивый код:
Array.prototype.max = function(){
var max = this[0];
for(var i = this.length-1; i > 0; i--) if(this[i] > max) max = this[i];
return max;
}
var a = [42, 100500, 13, 666];
alert(a.max());//100500
Любители PHP:
function max(a){
if(!(a instanceof Array)) return false;
if(a.length == 0) return null;
var max = a[0];
for(var i = a.length-1; i > 0; i--)if(a[i] > max) max = a[i];
return max;
}
var a = [42, 100500, 13, 666];
alert(max(a));//100500
Ну а теперь представим себе что нужно модифицировать такой "класс", как Object.
Допустим нам нужно узнать значение лексографически наибольшого ключа в объекте.
Просмотр всех ключей объекта можно сделать инструкцией for..in
for(key in obj)f();
PHP-версия:
function max_key(obj){
if(!(obj instanceof Object)) return false;
var max = null;
for(i in obj)
if(i > max || max == null)
max = i;
return max;
}
var obj = {
a: 42,
b: 100500,
c: 13
};
alert(max_key(obj));//c
В стиле JavaScript
Object.prototype.max_key = function(){
max = null;
for(var i in this)
if (i > max || max == null)
max = i;
return max;
}
var obj = {
a: 42,
b: 100500,
c: 13
}
alert(obj.max_key());//max_key
// EPIC FAIL
И тут наша js версия потерпела крах...
max_key тоже являеться ключом объекта, причем после строки
Object.prototype.max_key = function()...
Уже любого объекта.
Самый простой способ спасти JS-стиль, это использовать пустой объект и проверять есть ли в нём ключик с найденым именем.
(function(){
var _OBJECT = {};
Object.prototype.max_key = function(){
max = null;
for(var i in this)
if (!_OBJECT[i] && (i > max || max == null))
max = i;
return max;
}
})()
var obj = {
a: 42,
b: 100500,
c: 13
}
alert(obj.max_key());//c
// WIN?
Структурка (function(){code})() позволяет сразу выполнить "code" заприсанную внутри. Причем _OBJECT, являеться доступным только из функции Object.prototype.max_key()...
Продолжение следует...
Жду комментариев и вариантов решения. Вскоре опубликую ещё одну проблемму и возможное решение...
|
А .hasOwnProperty() отменили?
В стиле минималистка
Не надо вообще трогать прототипы встроенных объектов, это дурная практика.
А обсуждаемая функция реализуется с использованием стандартного синтаксиса так:
Object.keys
возвращает массив имён ключей.Math.max
не может принимать в качестве аргумента массив. Нужно передать массив в виде аргументов с помощьюapply
Можно создать свой класс, который будет наследовать от Array, и расширять уже его прототип. Из явных минусов — необходимость использоваться конструктора.
>Object.keys(obj)
>Object.create(Array.prototype);
Некроссбраузерно.