Получить имя свойства объекта в виде строки
Можно ли получить имя свойства объекта в виде строки
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
Ответы
Ответ 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
}