Маэстро,
при использовании for (... in ...) порядок перебора свойств в спецификации неопределён, поэтому разные браузеры перебирают их в разном порядке. Если нужно перебрать свойства в определённом порядке, следует использовать другие способы. |
У меня тоже мысли крутились вокруг "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
|
Цитата:
Короче, я вообще обошел проблему с сортировкой (см. пример выше) |
Цитата:
Цитата:
|
Цитата:
for (i in obj) length++; obj.length = 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;
|
Цитата:
Может надо делать obj.length = length - 1; ? |
Цитата:
http://es5.javascript.ru/x15.4.html#x15.4.4.12 вообще, самым быстрым вариантом будет вариант Slavenin, при приведении примитивов в объекты, конечно. Цитата:
Цитата:
Цитата:
было бы неплохо не учитывать унаследованные свойства и проверять ключ на принадлежность к числу.
var length = 0, i;
for (i in obj) if (obj.hasOwnProperty(i) && isFinite(i)) {
length += 1;
}
obj.length = 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
|
| Часовой пояс GMT +3, время: 14:10. |