Подтвердить что ты не робот

Получить имя свойства объекта в виде строки

Можно ли получить имя свойства объекта в виде строки

person = {};
person.first_name = 'Jack';
person.last_name = 'Trades';
person.address = {};
person.address.street = 'Factory 1';
person.address.country = 'USA';

Я хотел бы использовать это так:

var pn = propName( person.address.country ); // should return 'country' or 'person.address.country'
var pn = propName( person.first_name );      // should return 'first_name' or 'person.first_name'

ПРИМЕЧАНИЕ: этот код именно то, что я ищу. Я понимаю, это звучит даже глупо, но это не так.

Это то, что я хочу сделать с этим.

HTML

person = {};
person.id_first_name = 'Jack';
person.id_last_name = 'Trades';
person.address = {};
person.address.id_address = 'Factory 1';
person.address.id_country = 'USA';


extPort.postMessage
(
  {
    message : MSG_ACTION,
    propName( person.first_name ): person.first_name
  }
};

---------------------- ОТВЕТ -----------------------

Получил благодаря ибу. Он указал правильный путь, и я использовал рекурсивную функцию

var res = '';

function propName(prop, value) {
    for (var i in prop) {
        if (typeof prop[i] == 'object') {
            if (propName(prop[i], value)) {
                return res;
            }
        } else {
            if (prop[i] == value) {
                res = i;
                return res;
            }
        }
    }
    return undefined;
}

var pn = propName(person, person.first_name); // returns 'first_name'
var pn = propName(person, person.address.country); // returns 'country'

ДЕМО: http://jsbin.com/iyabal/1/edit

4b9b3361

Ответ 1

Да, вы можете с небольшим изменением.

function propName(prop, value){
   for(var i in prop) {
       if (prop[i] == value){
            return i;
       }
   }
   return false;
}

Теперь вы можете получить такое значение:

 var pn = propName(person,person.first_name);
 // pn = "first_name";

Примечание Я не уверен, для чего его можно использовать.

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

Ответ 2

Я знаю лучшую практику использования Object.keys(your_object). Он будет анализировать имя свойства массива для вас. Пример:

var person = { firstName: 'John', lastName: 'Cena', age: '30' };
var listPropertyNames = Object.keys(person); //["firstName", "lastName", "age"]

Я надеюсь, что этот пример полезен для вас.

Ответ 3

Вы можете обернуть ваше свойство в функцию, а затем преобразовать функцию в строку и получить свойство из нее.

Например:

function getPropertyName(propertyFunction) {
    return /\.([^\.;]+);?\s*\}$/.exec(propertyFunction.toString())[1];
}

Тогда использовать это:

var myObj = {
    myProperty: "testing"
};

getPropertyName(function() { myObj.myProperty; }); // myProperty

Остерегайтесь, что minifiers мог сломать это.

Редактировать: я создал преобразование компилятора, которое работает с babel и компилятором машинописного текста (см. Ts-nameof). Это гораздо надежнее, чем что-то делать во время выполнения.

Ответ 4

Вы можете сделать это, преобразовав все свойства объекта в функции, которые будут возвращать их собственные имена

var person = {};
person.firstname = 'Jack';
person.address = "123 Street";

function getPropertyName(obj, expression) {
    var res = {};
    Object.keys(obj).map(k => { res[k] = () => k; });
    return expression(res)();
}

let result = getPropertyName(person, o => o.address);
console.log(result); // Output: 'address'

Ответ 5

Использование прокси:

var propName = ( obj ) => new Proxy(obj, {
    get(_, key) {
        return key;
    } 
});


var person = {};
person.first_name = 'Jack';
person.last_name = 'Trades';
person.address = {};
person.address.street = 'Factory 1';
person.address.country = 'USA';

console.log(propName(person).first_name);
console.log(propName(person.address).country);

Ответ 6

Нет, это невозможно.

Представьте себе следующее:

person.age = 42;
person.favoriteNumber = 42;

var pn = propName(person.age)
// == propName(42)
// == propName(person.favoriteNumber);

Ссылка на имя свойства просто теряется в этом процессе.

Ответ 7

После ответа @David Sherret с ES6 это можно сделать очень просто:

propName = f => /\.([^\.;]+);?\s*\}$/.exec(f.toString())[1]
let prop = propName(() => {obj.name}); // myProperty

Ответ 8

Вы можете создать метод пространства имен для объекта. Метод должен будет мутировать объект таким образом, чтобы строки вместо этого вместо объекта сохраняли два свойства: a value и a _namespace.

DEMO: http://jsfiddle.net/y4Y8p/1/

var namespace = function(root, name) {
    root._namespace = name;
    function ns(obj) {
        for( var i in obj ) {
            var a = obj._namespace.split('.')
            if ( a.length ) {
                a.push(i);
            }
            if( typeof obj[i] == 'object' ) {
                obj[i]._namespace = a.join('.');
                ns(obj[i]);
                return;
            }
            if( typeof obj[i] == 'string' ) {
                var str = obj[i].toString();
                obj[i] = {
                    _namespace: a.join('.'),
                    value: str
                };
            }
        }
    }
    ns(root);
};

namespace(person, 'person');

console.log(person.address.street._namespace) // person.address.street
console.log(person.address.street.value) // 'Factory 1'

Итак, теперь вы можете сделать:

var o = { message: MSG_ACTION };
o[ person.first_name._namespace ] = person.first_name.value;

extPort.postMessage(o);

Ответ 9

Я в той же ситуации.

Вот ваш способ сделать это, используя Lodash или UnderScore, с единственным ограничением значения, которое будет уникальным:

var myObject = {
'a': 1,
'b': 2,
'c': 3
}
_.findKey(myObject, function( curValue ) { return myObject.a === curValue });

Обычный JavaScript

function getPropAsString( source, value ){
    var keys = Object.keys( source );

    var curIndex,
        total,
        foundKey;

    for(curIndex = 0, total = keys.length; curIndex < total; curIndex++){
        var curKey = keys[ curIndex ];
        if ( source[ curKey ] === value ){
            foundKey = curKey;
            break;
        }
    }

    return foundKey;
}

var myObject = {
'a': 1,
'b': 2,
'c': 3
}
getPropAsString( myObject, myObject.a )

Но я бы предпочел исправить код как решение. Пример:

var myObject = {
'a': {key:'a', value:1},
'b': {key:'b', value:2},
'c': {key:'c', value:3}
}

console.log( myObject.a.key )

Ответ 10

Я опаздываю на вечеринку, но я выбрал совершенно другой подход, поэтому я добавлю свой подход и посмотрю, что думает сообщество.

Я использовал Function.prototype.name чтобы делать то, что я хочу. мои свойства - это функции, которые при вызове возвращают значение свойства, и я могу получить имя свойства (которое является функцией), используя .name

Вот пример:

person = {
    firstName(){
        return 'John';
    },
    address(){
        return '123 street'
    }
}

person.firstName.name // 'firstName'
person.address.name // 'address'

Замечания:
в этом случае вы не можете легко изменить значение свойства (например, имя) во время выполнения. вам нужно создать функцию (в этом случае .name будет анонимным), и эта функция вернет новую именованную функцию, которая вернет новое значение:

// note the () at the end     
person.firstName = new Function('', 'return function firstName(){return "johny"}')(); 
person.firstName.name ; // 'firstName' 
person.firstName(); // 'johny'

Ответ 11

Мне нравятся лайнеры, вот общее решение:

const propName = (obj,type) => Object.keys(obj).find(key => obj[key] === type)

propName(person, person.age)

Ответ 12

Я предпочитаю это чисто и просто, как это:

var obj = {
  sessionId: 123,
  branchId: 456,
  seasonId: 789
};

var keys = Object.keys(obj);

for (var i in keys) {
  console.log(keys[i]); //output of keys as string
}