Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #21 (permalink)  
Старый 24.10.2012, 22:39
Профессор
Отправить личное сообщение для oneguy Посмотреть профиль Найти все сообщения от oneguy
 
Регистрация: 31.05.2012
Сообщений: 396

Маэстро,
при использовании for (... in ...) порядок перебора свойств в спецификации неопределён, поэтому разные браузеры перебирают их в разном порядке. Если нужно перебрать свойства в определённом порядке, следует использовать другие способы.

Последний раз редактировалось oneguy, 24.10.2012 в 22:43.
Ответить с цитированием
  #22 (permalink)  
Старый 24.10.2012, 22:44
Профессор
Отправить личное сообщение для Маэстро Посмотреть профиль Найти все сообщения от Маэстро
 
Регистрация: 02.07.2010
Сообщений: 642

У меня тоже мысли крутились вокруг "prototype", но до хэша имен ключей я так и не добрался.
Что касается Вашего примера, то (как я понял) в этом алгоритме надо каким-то образом всегда знать длину length (то ли подсчитывать её при присвоении свойств, то ли запускать общий подсчет позже).

Я считаю, что если вводить сортировку (чтобы привести в разных браузерах к единому виду), то это может потратить приличное время на больших массивах. Поэтому я вообще отказался от неё и в каком порядке идет перебор в "for (var key in m)" меня уже и не интересует.
Вот мой вариант решения:
m = {};
      
m[7]='7777';
m[6]='6666';
m[5]='5555';
m[1]='1111';
m[17]='1717';
m[2]='2222';
m[25]='2525';
m[3]='3333';
m[8]='8888';
      
var r = 4; // удаляем свойство №4 и сдвигаем все свойства с номерами более 4 на его место
      
var tmp = {};
for (var key in m) 
 {
 if (key > r)  
 tmp[key-1] = m[key];
 else tmp[key] = m[key];
 };
      
alert('4=' + m[4] + ' 5=' + m[5] + ' 6=' + m[6] + ' 7=' + m[7]); // 4=undefined 5=5555 6=6666 7=7777   
m = tmp;
alert('4=' + m[4] + ' 5=' + m[5] + ' 6=' + m[6] + ' 7=' + m[7]); // 4=5555 5=6666 6=7777 7=8888
Ответить с цитированием
  #23 (permalink)  
Старый 24.10.2012, 22:49
Профессор
Отправить личное сообщение для Маэстро Посмотреть профиль Найти все сообщения от Маэстро
 
Регистрация: 02.07.2010
Сообщений: 642

Сообщение от oneguy
при использовании for (... in ...) порядок перебора свойств в спецификации неопределён
Да, спасибо, я знаю это. Вопрос стоял в том, что если Google Chrome и Opera по состоянию на 2012г. делают этот перебор строго по возрастанию числовых ключей объекта, то можно ли на этом уверенно основываться, или нет никаких гарантий, что так будет и в будущем?
Короче, я вообще обошел проблему с сортировкой (см. пример выше)
Ответить с цитированием
  #24 (permalink)  
Старый 24.10.2012, 23:08
Аватар для trikadin
Модератор
Отправить личное сообщение для trikadin Посмотреть профиль Найти все сообщения от trikadin
 
Регистрация: 27.04.2010
Сообщений: 3,417

Сообщение от Маэстро
то можно ли на этом уверенно основываться, или нет никаких гарантий, что так будет и в будущем?
Сообщение от Маэстро
нет никаких гарантий, что так будет и в будущем
Ответ, собственно.
__________________
Читайте:
Ты любопытный) Всё-таки, ничему в этом мире не помешает хорошая доля юмора)
Как спросить, чтобы вам ответили
Часто Задаваемые Вопросы (FAQ)
Ответить с цитированием
  #25 (permalink)  
Старый 24.10.2012, 23:15
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

Сообщение от Маэстро
Что касается Вашего примера, то (как я понял) в этом алгоритме надо каким-то образом всегда знать длину length (то ли подсчитывать её при присвоении свойств, то ли запускать общий подсчет позже).
сделать один раз
for (i in obj) length++;
obj.length = length;

после этого добавлять \ уменьшать это значение при добавлении \ удалении элементов - т.е. придётся делать это через серреты и геттеры.
Ответить с цитированием
  #26 (permalink)  
Старый 25.10.2012, 11:45
Профессор
Отправить личное сообщение для Маэстро Посмотреть профиль Найти все сообщения от Маэстро
 
Регистрация: 02.07.2010
Сообщений: 642

Сообщение от melky
Array.prototype.splice.call(myObj, 2, 1);
Вообще мне нравятся решения "в одну строку". Я, пожалуй, всё же возьму Ваш вариант. Только у меня пока еще есть смутные сомнения насчет него - надо всячески потестировать при разных вариантах заполнения объекта и удаления его свойств, проверить быстродействие.

Цитата:
Если и это не подходит, значит, придётся реализовывать своюь структуру данных, где выборка по ключу будет O(1), и в которой так же можно будет менять ключ.
мне кажется, что это будет трудно
А вот посмотрите/прокомментируйте, пожалуйста, примерчик, который я нашел в инете. В частности касательно установки length:
//for (i in obj) length++; obj.length = length; // melky

Array.prototype.associate = function(keys){
    var obj = {}, length = Math.min(this.length, keys.length);
    for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
    return obj;
};

var hash = ['one', 'three', 'two'].associate(['first','3','2']);

var string = '';

for (var i in hash) string += i + ':' + hash[i] + '; ';

alert(string);
// Chrome: 2:two; 3:three; first:one;
// Opera:  2:two; 3:three; first:one;
// FF: first:one; 3:three; 2:two; 
// IE: first:one; 3:three; 2:two;
Ответить с цитированием
  #27 (permalink)  
Старый 25.10.2012, 13:48
Профессор
Отправить личное сообщение для Маэстро Посмотреть профиль Найти все сообщения от Маэстро
 
Регистрация: 02.07.2010
Сообщений: 642

Сообщение от melky Посмотреть сообщение
сделать один раз
for (i in obj) length++;
obj.length = length;
А всё-таки, в Вашем алгоритме свойство length что должно хранить? Потому как for (i in obj) length++; при подсчете количества учтет не только свойства с числовыми индексами, но еще прибавит к счетчику и само свойство length.
Может надо делать obj.length = length - 1; ?
Ответить с цитированием
  #28 (permalink)  
Старый 25.10.2012, 16:46
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

Сообщение от Маэстро
Вообще мне нравятся решения "в одну строку". Я, пожалуй, всё же возьму Ваш вариант. Только у меня пока еще есть смутные сомнения насчет него - надо всячески потестировать при разных вариантах заполнения объекта и удаления его свойств, проверить быстродействие.
вот дока, на всякий.
http://es5.javascript.ru/x15.4.html#x15.4.4.12

вообще, самым быстрым вариантом будет вариант Slavenin, при приведении примитивов в объекты, конечно.

Сообщение от Маэстро
А вот посмотрите/прокомментируйте, пожалуйста, примерчик, который я нашел в инете. В частности касательно установки length:
он так же не позволяет изменять ключи.

Сообщение от Маэстро
А всё-таки, в Вашем алгоритме свойство length что должно хранить?
длину значений - см. массив.

Сообщение от Маэстро
при подсчете количества учтет не только свойства с числовыми индексами, но еще прибавит к счетчику и само свойство length.
конечно. код слишком упрощён, чтобы его использовать в голом виде

было бы неплохо не учитывать унаследованные свойства и проверять ключ на принадлежность к числу.
var length = 0, i;
for (i in obj) if (obj.hasOwnProperty(i) && isFinite(i)) {
    length += 1;
}
obj.length = length;
Ответить с цитированием
  #29 (permalink)  
Старый 25.10.2012, 17:02
Профессор
Отправить личное сообщение для Маэстро Посмотреть профиль Найти все сообщения от Маэстро
 
Регистрация: 02.07.2010
Сообщений: 642

Сообщение от melky
length - длину значений - см. массив.
Сообщение от melky
было бы неплохо не учитывать унаследованные свойства и проверять ключ на принадлежность к числу.
Короче говоря, я тщательно исследовал Ваш код (пример) и пришел к выводу, что со свойством length надо быть осторожным.
Не знаю, что Вы подразумевали под "длиной значений", но для нормальной работы Вашего алгоритма в length должно быть не количество элементов (свойств объекта), а максимальный индекс свойства (это максимальное значение ключа), увеличенный на 1. Причем IE как всегда выпендрился: ему не надо к length прибавлять 1, иначе в объекте остается одно лишнее свойство (последнее). Код получился такой:
var myObj = {};
      myObj.length = 0; // это не количество элементов, а максимальный индекс + 1
      
myObj[1]= "1";
myObj[3]= "3";
myObj[2]= "2";     
myObj[0]= "0";
myObj[100]= "100";
myObj[99]= "99";  
     
var length = 0; 
      
// подсчет length как количества свойств
///for (i in myObj) length++; 
      
// подсчет length как максимального индекса      
for (i in myObj)
 {
 if (i > length) length = Number(i);
 };
if (window.IE)
myObj.length = length; 
else myObj.length = length + 1;

var s = '';
for (var key in myObj) s = s + ' ' + key + '=' + myObj[key];
alert('1). ' + s); 
// 1).  0=0 1=1 2=2 3=3 99=99 100=100 length=101

      Array.prototype.splice.call(myObj, 2, 1); // удаляем один элемент
      
var s = '';
for (var key in myObj) s = s + ' ' + key + '=' + myObj[key];
alert('2). ' + s); 
// 2).  0=0 1=1 2=3 98=99 99=100 length=100
Ответить с цитированием
Ответ


Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как обратиться к свойству объекта по имени если оно хранится в переменной xaknik Общие вопросы Javascript 2 25.04.2012 23:12
Может ли свойство объекта быть массивом??? Alexeich Общие вопросы Javascript 25 21.11.2011 13:47
Как поменять свойство плагина? lyapharov jQuery 2 16.04.2011 19:39
Как по событию вызвать метод определенного экземпляра объекта jvs jQuery 3 24.12.2009 16:04
как узнать тип значения объекта? VHS Общие вопросы Javascript 1 07.01.2009 23:57