LINUX.ORG.RU

Обращение к свойству по имени

 


0

2

В JS, я на данный момент, чтобы вытащить имя свойства из объекта, делаю примерно так

ob={foo: 1, bar: 2}
for(i in ob){if(i==="foo") "It's ok"}
Но полноценного доступа по-прежнему нет, например, нельзя заменить строку «foo» на «anoter_foo», чтобы этот another_foo, по-прежнему указывал на 1. Да и сам по себе цикл, неоптимален, так как сажает производительность, наверное, хотя я в этом не смыслю. А не плохо было бы иметь что то вроде такого
ob={foo: 1, bar: 2}
ob.callByName("foo")="baz"
console.log(ob) // --> {baz: 1, bar: 2}
А еще лучше было бы, чтобы объект был доступен как строка, и можно было бы его просто пропарсить. Нет ли таких средств в JS?



Последнее исправление: anonimous (всего исправлений: 1)

Яннп. ob.foo == ob['foo']. JSON.stringify({foo: 1}).

zz ★★★★
()

Обращайся как к массиву, юзай delete

ob={foo: 1, bar: 2}
for(i in ob){
    console.log(ob[i]); // 1, 2
}
var tmp = ob.foo;
delete ob.foo;
ob.baz = tmp;
delete tmp;
Как сделать замену красивее я не знаю. Да и вообще, что это за задача такая? Нельзя ли поменять местами ключи со значениями? Т.е. ob={1: 'foo', 2: 'bar'}; Но и в таком случае лучше тогда наверное использовать массив, если ничего более хранить не требуется.

Kilte ★★★★★
()
Ответ на: комментарий от Kilte

Нельзя ли поменять местами ключи со значениями?

Не, просто ключи, значения не трогать.

anonimous
() автор топика
Ответ на: комментарий от anonimous

А больше ты никак не сделаешь, насколько я знаю.

Kilte ★★★★★
()
Ответ на: комментарий от Hater

Да у меня конкретной задачи нет никакой, может оно и подойдет в большинстве случаев, хз, надо подумать.

anonimous
() автор топика
Ответ на: комментарий от Hater

Первое, что приходит в голову

pr={baz: 3}
ob={foo: 1, bar: 2, __proto__: pr}

ob.superbaz=ob.baz
delete ob.baz

console.log(ob.baz) // 3
причем, что интересно, delete ob.baz возвращает true почему то.

anonimous
() автор топика
Ответ на: комментарий от anonimous

А, ну да, delete вообще, по-ходу, всегда возвращает true, есть ли свойство, нет его в объекте, ему срать. Оно false возвращает, наверное, только если свойство нельзя удалить, а если его нет, ему срать, оно отрабатывает «успешно», гы-гы.

anonimous
() автор топика
Ответ на: комментарий от anonimous

__proto__
почти недокументирован
чайнинг лукапов

Какой же убогий огрызок этот ваш жоэс.

По теме: кей-валю таблицы обычно хешируются по ключам для ускорения лукапов, так что инплейс замена ключа бессмысленна, т.к. наверняка меняется его хеш. Таблица могла бы предоставить метод replace_key, но зачем, если эта операция элементарна на гет-сетах?

Кстати в жоэсе что, ob.key=null/nil/undef/none не удаляет ключ? Нельзя просто if ob.key проверять, хотя бы на уровне соглашений? Если есть delete, то где тогда defined/exists? Все правда так плохо?

arturpub ★★
()
Ответ на: комментарий от arturpub

Кстати в жоэсе что, ob.key=null/nil/undef/none не удаляет ключ?

Нет

Нельзя просто if ob.key проверять,

ob.key тебе дает сразу значение. Если оно выставлено в undefined, это не даст инфы о наличии/отсутствии ключа, потому что по умолчанию все неопределенные тоже undefined.

Если есть delete, то где тогда defined/exists?

можно вот-так


ob={one: 1, two: 2}
ob.one=undefined
for(i in ob){console.log(i)} // one two
delete ob.one
for(i in ob){console.log(i)} // two

Все правда так плохо?

А что тут плохого? Что сахара нет? Можно из того же for (i in ob) функцию проверки если надо. Но на практике, это редко требуется, ИМХО. Как правило, пох, остался ключ или нет. Может когда-нибудь, разве что на производительности скажется, я хз.

anonimous
() автор топика
Ответ на: комментарий от arturpub

Вообще то, зря ты на __proto__ наезжаешь. JS — Это один из немногих ЯП, в которых осталось Ъ-ООП, в стиле смолтока/селфа. __proto__, это его часть, как бы. Он достаточно прозрачен, и нех*я там документировать особо, мне кажется.

anonimous
() автор топика
Ответ на: комментарий от amomymous

Ну а как с помощью eval'а это сделать? Ведь объект не строка, его не пропарсишь. Если бы объект имел представление в виде строки, как функция например, f.toString(), разговора бы не было. Но объект в виде строки, по-моему, не представлен. Я не говорю про JSON.stringify(), это все фигня, потому что целиком объект с прототипами он не даст, помоему.

anonimous
() автор топика
Ответ на: комментарий от invy

Что это? Это ты просто сделал ob={foo: «blahblah»}, создал свойство, и все. А вопрос в том, чтобы достать это foo (имя само), и делать с ним что хочешь.

anonimous
() автор топика

Норкоман, зачем ты меняешь ключ? Если «просто так», то лучше брось, пока задача не появится.

Deleted
()
Ответ на: комментарий от Deleted

Да не зачем, просто много говориться о том что в JS инроспекция во все края, вот я и задался вопросом, можно ли именами свойств манипулировать произвольным образом.

anonimous
() автор топика
Ответ на: комментарий от anonimous

Нынче много что говорят. JavaScript «везде» вовсем не потому, что он хорош. Собственно, какие ты свойства там нашёл, это ж обычные ключи. Там ещё нормальные классы не изобрели (только прототипированный ужас, летящий на крыльях ночи), хотя грозятся добавить синтаксических сахар.

Deleted
()
Последнее исправление: Mystra_x64 (всего исправлений: 1)
Ответ на: комментарий от Deleted

Там ещё нормальные классы не изобрели

Нормальные классы — это замыкания. И они скорей не_нужны, чем нужны.

только прототипированный ужас, летящий на крыльях ночи

это же Ъ-ООП

хотя грозятся добавить синтаксических сахар.

Ка будто что-то хорошее

anonimous
() автор топика
Ответ на: комментарий от anonimous

Нормальные классы — это замыкания.
Ъ-ООП

Норкоман.

Deleted
()
Ответ на: комментарий от anonimous

Там где-то сказано «класс»? Там написано «ужас». Читаем внимательнее.

Deleted
()

«foo» на «anoter_foo», чтобы этот another_foo, по-прежнему указывал на 1

Если чтобы оставить на своих местах, то без копирования никак. Набросал, делает то что надо:

function replaceKey(obj, oldKey, newKey) {
    var i, found = false, newObj = {};
    for (i in obj) {
        if (obj.hasOwnProperty(i)) {
            if (i === oldKey) {
                newObj[newKey] = obj[oldKey];
                found = true;
            } else {
                newObj[i] = obj[i];
            }
        }
    }
    if (!found) {
        newObj[newKey] = undefined;
    }
    return newObj;
}

var x = {a: 1, b: 2};
console.log(x); // Object { a=1, b=2}
x = replaceKey(x, 'a', 'c');
console.log(x); // Object { c=1, b=2}
При замене несуществующего добавляет новый ключ. Оптимизации никакой, тупо цель достигнута. Насчет интерфейса - хз, думаю нет смысла его менять, пусть уж лучше динамически умрет все что не нужно после выхода из ф-ции.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

По-моему, можно проще сделать

x={a: 1, b: 2}

replaceKey=function(ob, oldKey, newKey){
   for(var i in ob){
      if(i===oldKey){ob[newKey]=ob[oldKey]; ob[oldKey]=undefined}
   }
}

replaceKey(x, "a", "c") 

console.log(x) // { a: undefined, b: 2, c: 1 }
И можно, конечно, проверку hasOwnProperty туда добавить, но тогда для таких вот случаев не будет работать
x={b: 2, __proto__: {a: 1}}
replaceKey(x, "a", "c") 

console.log(x) // { b: 2, c: 1, a: undefined }
console.log(x.__proto__.a) // 1 still
Но я, вообще-то, думал, просто, точней, надеялся, что в языке есть встроеные средства для непосредственного манипулирования кеями вне зависимости от values.

anonimous
() автор топика
Ответ на: комментарий от anonimous

надеялся, что в языке есть встроеные средства

Точно таких нет, причину назвали где-то выше - хеши.

deep-purple ★★★★★
()
Ответ на: комментарий от anonimous

По-моему, можно проще сделать

Я написал развернуто, дальше оптимизируй как захочется, если решение подходит.

__proto__

Нахрена в прото лазить?

{ a: undefined, b: 2, c: 1 }

И куда значение x.a просрать успел? )))

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

Нахрена в прото лазить?

Ну, это зависит от юзкейса. Иногда надо, я думаю.

И куда значение x.a просрать успел? )))

А зачем оно нужно? Мы ведь хотели заменить его?

anonimous
() автор топика
Ответ на: комментарий от deep-purple

И куда значение x.a просрать успел? )))

Можно его было просто удалить, но, опять же, тогда на прототипах не будет работать.

anonimous
() автор топика
Ответ на: комментарий от anonimous

Ну, это зависит от юзкейса. Иногда надо, я думаю.

Я подумал о том что тебе может и надо уже после того как запостил ответ. Вобщем проехали это.

А зачем оно нужно? Мы ведь хотели заменить его?

Эмм, ну вот посмотри в моем примере все св-ва остались в тех же местах, в том же порядке, и только нужное было переименовано. И никаких тебе лишних «мертвых» ключей, никакого нарушения порядка следования, как x.b был вторым, так и остался - т.е. все чистенько. Ну и в самом топике ты как-бы это и писал в требованиях, я так и запилил.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

никакого нарушения порядка следования

А там порядок и не нужен особо. Когда он может потребоваться? Если объект с миллионом полей, чтобы быстрей поиск проходил? Я с таким не сталкивался пока.

никаких тебе лишних «мертвых» ключей

if (!found) {
        newObj[newKey] = undefined;
    }

Вот эта ветка оставит мертвый ключ. Но это не особо важно. Кстати, она вообще лишняя, по-моему, зачем она нужна?

anonimous
() автор топика
Ответ на: комментарий от anonimous

можно вот-так

Мда уж. Теперь ясен смысл топика.

Ъ-ООП смаллталк олдскул

Я не веб, у меня встроеный луа, вот он правда тот самый вкус, тот самый чай, а со всеми мыслимыми примитивами — окружениями, корутинами, метаметодами и тривиальщиной в виде скопинга и замыканий, и сквозным житом — я честно говоря не встречал такой мазовой комбинации. Я конечно фанбой тот еще, но выбор отточен годами, глянь на досуге, книжка PiL многое прояснит почему я ругаюсь на __прото :)

arturpub ★★
()
Ответ на: комментарий от anonimous

она вообще лишняя, по-моему, зачем она нужна?

Так я же написал:

При замене несуществующего добавляет новый ключ

Если тебе это не нужно, то смело выкинь. написано я-ля «можно и так, если нужно»

порядок и не нужен особо

Тогда да, все проще:

replaceKey = function(obj, oldKey, newKey) {
    if (typeof obj[oldKey] !== 'undefined') {
        obj[newKey] = obj[oldKey];
        delete obj[oldKey];
    }
}

var x = {a: 1, b: 2};
console.log(x);
replaceKey(x, 'a', 'c');
console.log(x);
Но! Внимание! Если будет реально такой объект:

{a:1,b:2,c:undefined}

то естессно проверка не пройдет, и св-во не зареплейсит. И тут опять встревает hasOwnProperty() которое таки проверит есть ли реально такое св-во вообще у нашего объекта:

if (obj.hasOwnProperty(oldKey)) { ...
Вобщем думай сам что тебе подойдет, та или эта проверка.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

А зачем там проверка typeof?

replaceKey = function(obj, oldKey, newKey) {
    if (obj[oldKey]) {
        obj[newKey] = obj[oldKey];
        delete obj[oldKey];
    }
}
Так все прекрасно работает.

то естессно проверка не пройдет, и св-во не зареплейсит.

Все реплесится прекрасно. Не вижу разницы.

anonimous
() автор топика
Ответ на: комментарий от deep-purple

то естессно проверка не пройдет, и св-во не зареплейсит

Не зареплейсит если вот так будет

    if (typeof obj[newKey] !== 'undefined') {
Только зачем эти заморочки нужны, я хз.

anonimous
() автор топика
Ответ на: комментарий от anonimous

Проверка typeof проверяет только на undefined, твоя проверка - зацепит все значения, которые приведутся к false. (http://ecma262-5.com/ELS5_HTML.htm#Section_9.2)

Ja-Ja-Hey-Ho ★★★★★
()
Последнее исправление: Ja-Ja-Hey-Ho (всего исправлений: 1)
Ответ на: комментарий от anonimous

ИМХО лучше проверять так:

if (newKey in obj) { … }
Ибо свойство объекта может иметь значение undefined. Например:
var o = {a: undefined, b: ''};
replaceKey(o, 'a', 'b');
console.log('Ooops!', o);

Ja-Ja-Hey-Ho ★★★★★
()
Последнее исправление: Ja-Ja-Hey-Ho (всего исправлений: 1)
Ответ на: комментарий от Ja-Ja-Hey-Ho

Да, ступил, так не заменяться ключи со значениям приводимым к false. Вот поэтому я и говорю, что работать непосредственно с ключами удобней. вот этот код вроде такой фигней не должен страдать.

anonimous
() автор топика
Ответ на: комментарий от Ja-Ja-Hey-Ho

Да-да, я о том же:). Вот я и в начале топика написал

А не плохо было бы иметь что то вроде такого

ob={foo: 1, bar: 2}
ob.callByName("foo")="baz"
console.log(ob) // --> {baz: 1, bar: 2}
anonimous
() автор топика

В JS, я на данный момент, чтобы вытащить имя свойства из объекта, делаю примерно так

Но зачем???

Почему не

if ('foo' in ob) { "It's ok" }

или

if (ob.hasOwnProperty('foo')) { "It's ok" }

если не нужны унаследованные свойства?

В чём сакральный смысл перебора ВСЕХ ключей?

Apple-ch ★★
()
Ответ на: комментарий от Apple-ch

if ('foo' in ob) { «It's ok» }

Да, вот это, кажется лучше, спасибо. Я чет забыл об этой конструкции вообще.

anonimous
() автор топика
Ответ на: комментарий от Apple-ch

А вообще, основной посыл был в том, что хорошо было бы вот так, вообще

ob={foo: 1, bar: 2}
ob.callByName("foo")="baz"
console.log(ob) // --> {baz: 1, bar: 2}
потому что
if ('foo' in ob) { тут мы все равно не можем делать с именем все что захотим }

anonimous
() автор топика
Ответ на: комментарий от Apple-ch

Вообще, нет, в for i in мы имеем доступ к имени, какой-никакой через переменную i, а в случае («foo» in ob) — вообще никакого.

anonimous
() автор топика
Ответ на: комментарий от anonimous

JavaScript: The Definitive Guide

delete expects its operand to be an lvalue. If it is not an lvalue, the operator takes no
action and returns true. Otherwise, delete attempts to delete the specified lvalue.
delete returns true if it successfully deletes the specified lvalue. Not all properties can
be deleted, however: some built-in core and client-side properties are immune from
deletion, and user-defined variables declared with the var statement cannot be deleted.
Functions defined with the function statement and declared function parameters can-
not be deleted either.

zarkone ★★
()
Ответ на: комментарий от zarkone

If it is not an lvalue, the operator takes no

action and returns true. Наверное, точней было бы «если в обекте нет данного имени, возвращается true», а тут как-то «если его операнд не lvalue» — это не совсем то, этот Фленаган, похоже, слегка болен плюсами головного мозга.

anonimous
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.