Javascript.RU

Полемика о 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()...

Продолжение следует...

Жду комментариев и вариантов решения. Вскоре опубликую ещё одну проблемму и возможное решение...

+2

Автор: Гость (не зарегистрирован), дата: 1 июня, 2012 - 15:28
#permalink

А .hasOwnProperty() отменили?


Автор: dima_zluka, дата: 2 июня, 2012 - 17:09
#permalink

В стиле минималистка

Array.prototype.max=function(){
  return Math.max.apply(Math,this);
}

[4324,36,2134,65632435,34].max(); //65632435

Автор: torbasow, дата: 3 июня, 2012 - 16:40
#permalink

Не надо вообще трогать прототипы встроенных объектов, это дурная практика.

А обсуждаемая функция реализуется с использованием стандартного синтаксиса так:

Math.max(Object.keys(obj))

Автор: dima_zluka, дата: 4 июня, 2012 - 17:53
#permalink

var obj={
  a:12,
  b:30,
  c:2
}
Math.max(Object.keys(obj)) //NaN

Object.keys(obj) //["a", "b", "c"]

Object.keys возвращает массив имён ключей.
Math.max не может принимать в качестве аргумента массив. Нужно передать массив в виде аргументов с помощью apply


Автор: podgorniy, дата: 21 июня, 2012 - 22:46
#permalink

Можно создать свой класс, который будет наследовать от Array, и расширять уже его прототип. Из явных минусов — необходимость использоваться конструктора.

function ExtendedArray () {}

ExtendedArray.prototype = Object.create(Array.prototype);

ExtendedArray.prototype.max = function () {
	return Math.max.apply(Math, this);
}

var a = new ExtendedArray();
a.push(10)
a.push(20)
a.push(5);
a.max(); // 20

Автор: zenitchik (не зарегистрирован), дата: 13 августа, 2012 - 12:12
#permalink

>Object.keys(obj)
>Object.create(Array.prototype);

Некроссбраузерно.


Отправить комментарий

Приветствуются комментарии:
  • Полезные.
  • Дополняющие прочитанное.
  • Вопросы по прочитанному. Именно по прочитанному, чтобы ответ на него помог другим разобраться в предмете статьи. Другие вопросы могут быть удалены.
    Для остальных вопросов и обсуждений есть форум.
P.S. Лучшее "спасибо" - не комментарий, как все здорово, а рекомендация или ссылка на статью.
Содержание этого поля является приватным и не предназначено к показу.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Разрешены HTML-таги: <strike> <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <u> <i> <b> <pre> <img> <abbr> <blockquote> <h1> <h2> <h3> <h4> <h5> <p> <div> <span> <sub> <sup>
  • Строки и параграфы переносятся автоматически.
  • Текстовые смайлы будут заменены на графические.

Подробнее о форматировании

CAPTCHA
Антиспам
8 + 8 =
Введите результат. Например, для 1+3, введите 4.
 
Поиск по сайту
Другие записи этого автора
Больше записей нет. Прокомментируйте эту запись - может быть, тогда он что-нибудь еще хорошее напишет ;)
Содержание

Учебник javascript

Основные элементы языка

Сундучок с инструментами

Интерфейсы

Все об AJAX

Оптимизация

Разное

Дерево всех статей

Популярные таги
Последние комментарии
Последние темы на форуме
Forum