Get object property name as a string

JavascriptStringObjectProperties

Javascript Problem Overview


Is it possible to get the object property name as a string

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

I'd like to use it like this:

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'

NOTE: this code is exactly what I'm looking for. I understand it sounds even stupid, but it's not.

This is what I want to do with it.

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
  }
};

----------------------ANSWER-----------------------

Got it thanks to ibu. He pointed the right way and I used a recursive function

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'

DEMO: http://jsbin.com/iyabal/1/edit

Javascript Solutions


Solution 1 - Javascript

I know a best practice that using Object.keys(your_object). It will parse to array property name for you. Example:

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

I hope this example is useful for you.

Solution 2 - Javascript

You can accomplish this by converting all object properties into functions which will return the their own names

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'

Solution 3 - Javascript

You can wrap your property in a function and then convert the function to a string and get the property out of it.

For example:

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

Then to use it:

var myObj = {
    myProperty: "testing"
};

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

Beware that minifiers could break this.

Edit: I have created a compiler transform that works with babel and the typescript compiler (see ts-nameof). This is a much more reliable than doing something at runtime.

Solution 4 - Javascript

If anyone's looking for a TypeScript version of MarsRobot's answer, try this:

function nameof<T>(obj: T, expression: (x: { [Property in keyof T]: () => string }) => () => string): string
{
    const res: { [Property in keyof T]: () => string } = {} as { [Property in keyof T]: () => string };

    Object.keys(obj).map(k => res[k] = () => k);

    return expression(res)();
}

Usage:

const obj = { 
    property1: 'Jim',
    property2: 'Bloggs',
    property3: 'Bloggs',
    method: () => 'a string',
    child: { property4: 'child1' }
};

const test1 = nameof(obj, x => x.property1);
const test2 = nameof(obj, x => x.property2);
const test3 = nameof(obj, x => x.method);
const test4 = nameof(obj.child, x => x.property4);

console.log(test1);    // -> 'property1'
console.log(test2);    // -> 'property2'
console.log(test3);    // -> 'method'
console.log(test4);    // -> 'property4'

This version works even when objects have multiple properties with the same value (unlike some of the other answers above), and with editors like Visual Studio will provide intellisense for the property names when you get here: nameof(obj, x => x.

Solution 5 - Javascript

Using Proxy:

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);

Solution 6 - Javascript

I like one liners, here's a generic solution:

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

propName(person, person.age)

Solution 7 - Javascript

Yes you can, with a little change.

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

Now you can get the value like so:

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

Note I am not sure what it can be used for.

Other Note wont work very well with nested objects. but then again, see the first note.

Solution 8 - Javascript

I use the following in TypeScript. This way retains type-information and disallows selecting non-existing property keys.

export function getPropertyName<T extends object>(obj: T, selector: (x: Record<keyof T, keyof T>) => keyof T): keyof T {
  const keyRecord = Object.keys(obj).reduce((res, key) => {
    const typedKey = key as keyof T
    res[typedKey] = typedKey
    return res
  }, {} as Record<keyof T, keyof T>)
  return selector(keyRecord)
}

const obj = {
  name: 'test',
  address: {
    street: 'test',
  }
}

console.log(getPropertyName(obj, (x) => x.name)) // name
console.log(getPropertyName(obj.address, (x) => x.street)) // street

Solution 9 - Javascript

Following up on @David Sherret's answer with ES6 it can be made super simple:

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

Solution 10 - Javascript

I prefer it clean and simple like this:

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
}

Solution 11 - Javascript

You could create a namespacing method for the object. The method will need to mutate the object so that the strings becomes an object instead to hold two properties, a value and 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'

So now you can do:

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

extPort.postMessage(o);

Solution 12 - Javascript

I am in same situation.

Here is thy way to get it done using Lodash or UnderScore library, with one limitation of value to be unique:

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

Plain 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 )

But, I would prefer to fix the code as solution. An example:

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

console.log( myObject.a.key )

Solution 13 - Javascript

I am late to the party but I took a completely different approach, so I will throw in my approach and see what the community thinks.

I used Function.prototype.name to do what I want. my properties are functions that when called return the value of the property, and I can get the name of the property (which is a function) using .name

Here is an example:

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

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

Note:
you can't easily change the value of a property (e.g firstname) at run time in this case. you would need to create a function (.name would be anonymous in this case) and this function would return a new named function which return the new value:

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

Solution 14 - Javascript

No, it's not possible.

Imagine this:

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

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

The reference to the property name is simply lost in that process.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCLiFoSView Question on Stackoverflow
Solution 1 - JavascriptTriet NguyenView Answer on Stackoverflow
Solution 2 - JavascriptMarsRobotView Answer on Stackoverflow
Solution 3 - JavascriptDavid SherretView Answer on Stackoverflow
Solution 4 - JavascriptMadSkunkView Answer on Stackoverflow
Solution 5 - JavascriptIsk1nView Answer on Stackoverflow
Solution 6 - JavascriptNimrodView Answer on Stackoverflow
Solution 7 - JavascriptIbuView Answer on Stackoverflow
Solution 8 - JavascriptIACM-KFView Answer on Stackoverflow
Solution 9 - JavascriptNimrodView Answer on Stackoverflow
Solution 10 - JavascriptMaximilian FixlView Answer on Stackoverflow
Solution 11 - JavascriptDavid HellsingView Answer on Stackoverflow
Solution 12 - JavascriptAmit BhagatView Answer on Stackoverflow
Solution 13 - JavascriptMoha the almighty camelView Answer on Stackoverflow
Solution 14 - JavascriptScott SauyetView Answer on Stackoverflow