Как переименовать свойство объекта?
// создаем объект 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:04. |