Как переименовать свойство объекта?
// создаем объект
var m={};
// создаем у него три свойства и присваиваем им значения
m[5]='mama';
m[6]='papa';
m[7]='deda';
// или так:
m.x='mama';
m.y='papa';
m.z='deda';
alert(m[4] + ' ' + m[5] + ' ' + m[6] + ' ' + m[7]); // undefined mama papa deda
// как переименовать свойство "5" в свойство "4", чтобы при обращении к m[4] мы бы получили значение из бывшего m[5], а m[5] типа исчезло вообще?
// имеется ввиду не копирование m[4]=m[5];
|
перезаписываете, удаляете
m = {};
m.a = 'a';
m.b = 'b';
m.c = 'c';
m.b = m.a;
delete m.a;
console.log(m);
|
Цитата:
1. В примере я упрощенно написал m[5]='mama'; m[6]='papa'; m[7]='deda';Но вместо 'mama' и 'papa' в данных свойствах могут храниться другие многомегабайтные объекты. Присвоение одного свойства другому приведет (я так интуитивно считаю) к перегону больших массивов информации по памяти из одного места в другое. А если в объекте m несколько тысяч свойств, то процедура будет работать долго. 2. Показанный мною пример - это упрощенный случай задачи (тоже несколько упрощаю формулировку): Есть объект m={}; причем подчеркиваю, что это не массив m=[]; Данный объект содержит тысячу свойств m[1]...m[1000]. Необходимо удалить 100-е свойство из данного объекта, и все свойства, что имеют ключ > 100 сместить "вниз", в сторону меньших индексов. То есть 101-е свойство должно стать сотым, 102-е перейти на 101-е,... 1000-е перейти на 999-е. На ум приходит организовать цикл - перебор свойств и "перенос" данных из одного свойства в другое: for (var key in m) m[key-1] = m[key];Это работает! Однако, как всегда кто-нибудь это обезобразит! Проверка в разных браузерах показала, что -перебор от млаших к старшим key идет только в Opera и Google Chrome. -в Fire Fox перебор идет в том же порядке, в котором шло присвоение свойств -в IE также как и в Fire Fox перебор идет в том же порядке, в котором шло присвоение свойств, однако после прохода последнего элемента, созданного до цикла начинается просмотр элементов, созданных в цикле (что приводит к зависанию...) т.е. если присвоение было не последовательно в порядке возрастания ключей m[7]='deda'; m[6]='papa'; m[5]='mama'; m[1]='1111'; m[17]='1717'; m[2]='2222'; m[25]='2525'; m[3]='3333'; то Fire Fox и IE дадут кашеобразный результат. |
Цитата:
т.е. многомегабайтовый объект останется валяться там, где валялся. чтобы легко менять ключи, организуйте |
Цитата:
|
Цитата:
var m1 = {};
var m2 = {};
var m3 = {};
m1[5]='mama';
m2=m1; // присвоение по ссылке
m3[5] = m1[5]; // присвоение не по ссылке (копирование/дублирование данных)
m1[5] = 'privet'; // изменим объект m1 - повлияет ли он на m2 и m3?
alert('m1[5]=' + m1[5] + ' m2[5]=' + m2[5] + ' m3[5]=' + m3[5]);
// выведет: m1[5]=privet m2[5]=privet m3[5]=mama
|
Цитата:
2. у меня объект m={}; |
Цитата:
Учим матчасть, короче. |
Допишу примерчик ещё:
var m1 = {};
var m2 = {};
var m3 = {};
m1[5]={"bla": 123};
m2=m1;
m3[5] = m1[5];
m1["5"].bla = 12345
alert(m1[5].bla +" "+ m2[5].bla + " " + m3[5].bla)
|
Маэстро,
мдаа залёт конечно такой бред нести, ну ладно: Цитата:
Цитата:
2 Цитата:
3 Цитата:
|
Цитата:
-Думаю, что да. А Вы? P.S. можно, конечно, перед присвоением свойств объекту все примитивные типы еще погружать в объекты-оболочки, чтобы такие объекты копировались уже по ссылке... но не масло ли масляное? |
Цитата:
Я написал о двух проблемах в топике. Первую обсудили (будем так считать ). А что делать со второй? У меня есть своё решение с помощью создания второй копии массива m2={}, но оно мне не нравится по потреблению ресурсов (в какое-то время будет существовать две копии боольших массивов), поэтому хотелось бы услышать мнение профессионалов по более изящному варианту решения. |
Цитата:
|
Цитата:
|
Цитата:
Ну да черт с ним. А по вопросу сортировки свойств в объекте можете что-то подсказать? Хотя, идеально было бы делать то, что я назвал "переименованием" свойств объекта. Знаю, что все имена (названия свойств) - это хэш-массив. Как туда добраться? Есть способ? |
Цитата:
может, всё-таки поясните, зачем нужен сей велосипед и супер сила? |
Цитата:
мы не грузим их (грузовики) в кузов, а делаем точно такие же грузовики, загружаем их в кузов, а старые (грузовики) выкидываем. -во как ;) Цитата:
есть js-объект m, содержащий другие js-объекты (с черти-каким содержимым - там некие структуры и шифрованные данные). Назовем их "контейнеры". Все свойства объекта m нумеруются (обзываются) натуральными числами от 0 до nn=10000. Этим свойствам присвоены контейнеры. Требуется удалить любое свойство n при этом все остальные свойства от n+1 до nn должны сдвинуться в сторону меньших номеров. n+1 должно стать на место n, n+2 должно стать на место n+1 и т.д. |
Маэстро,
юзайте массивы и будет вам счастье ;) |
Цитата:
Я же говорил, что у меня не массив, а объект. И заменить его на массив я не могу. Только не спрашивайте почему - не уводите дискуссию в сторону. А то, что сортировка в разных браузерах хеша ключей разная - это тоже МОЯ проблема? Кстати, сортировку по возрастанию в Хроме даже осуждают! http://habrahabr.ru/qa/3749/ Вот только интересно, кто победит? Те, кто осуждают, или компания Гугл? |
Заимстоввание методов не пробовали?
var myObj = {
"0": "0",
"1": "1",
"2": "2",
"3": "3",
"length": 4
};
alert( myObj["2"] ); // 2
Array.prototype.splice.call(myObj, 2, 1);
alert( myObj["2"] ); // 3
Если и это не подходит, значит, придётся реализовывать своюь структуру данных, где выборка по ключу будет O(1), и в которой так же можно будет менять ключ. мне кажется, что это будет трудно, посему желаю вам удачи. вообще, такая структура данных у правил в CSS таблицах : http://javascript.ru/forum/misc/2680...kom-liste.html я с этим сталкивался уже. в принципе, можно глянуть в исходниках на Java, как они сделали эти списки, и так же сделать на JS - это как вариант. |
Маэстро,
при использовании 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, время: 12:48. |