web-dev-qa-db-fra.com

Obtenir le nom de la propriété de l'objet sous forme de chaîne

Est-il possible d'obtenir le nom de la propriété de l'objet sous forme de chaîne

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

Je voudrais l'utiliser comme ceci:

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'

Merci d'avance

NOTE: ce code correspond exactement à ce que je recherche. Je comprends que cela semble même stupide, mais ce n’est pas le cas.

C'est ce que je veux en faire.

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

----------------------RÉPONSE--------------------- -

Je l'ai eu grâce à ibu. Il a indiqué le bon chemin et j'ai utilisé une fonction récursive

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

29
CLiFoS

Oui, vous pouvez, avec un peu de changement.

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

Maintenant, vous pouvez obtenir la valeur comme suit:

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

Remarque Je ne suis pas sûr de savoir à quoi il peut être utilisé.

Autre Remarque ne fonctionnera pas très bien avec les objets imbriqués. mais là encore, voir la première note.

1
Ibu

Je connais une pratique exemplaire qui consiste à utiliser Object.keys (votre_objet) . Il analysera le nom de la propriété du tableau pour vous. Exemple:

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

J'espère que cet exemple vous sera utile.

18
Triet Nguyen

Vous pouvez envelopper votre propriété dans une fonction, puis la convertir en chaîne et en extraire la propriété.

Par exemple:

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

Puis l'utiliser:

var myObj = {
    myProperty: "testing"
};

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

Méfiez-vous que les minificateurs pourraient casser cela.

Edit: J'ai créé une transformation de compilateur qui fonctionne avec Babel et le compilateur TypeScript (voir ts-nameof ). C'est beaucoup plus fiable que de faire quelque chose au moment de l'exécution.

7
David Sherret

Vous pouvez accomplir cela en convertissant toutes les propriétés de l'objet en fonctions qui renverront leurs propres noms.

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'
4
Art S

Pour donner suite à la réponse de @David Sherret avec ES6, cela peut être rendu très simple:

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

Je suis en retard à la fête, mais j’ai adopté une approche complètement différente, je vais donc donner mon avis et voir ce que la communauté pense. 

J'ai utilisé Function.prototype.name pour faire ce que je veux . Mes propriétés sont des fonctions qui, lorsqu'elles sont appelées, renvoient la valeur de la propriété, et je peux obtenir le nom de la propriété (qui est une fonction) en utilisant .name

Voici un exemple:

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

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

Remarque:
vous ne pouvez pas facilement changer la valeur d’une propriété (par exemple, prenom) au moment de l’exécution dans ce cas . vous auriez besoin de créer une fonction (.name serait anonyme dans ce cas) et cette fonction renverrait un nouvelle fonction nommée qui renvoie la nouvelle valeur:

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

Je suis dans la même situation.

Voici comment vous pouvez le faire en utilisant Lodash ou UnderScore library, avec une limite de valeur unique:

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

JavaScript simple

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 )

Mais, je préférerais corriger le code comme solution. Un exemple:

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

console.log( myObject.a.key )
0
Amit Bhagat

Non, ce n'est pas possible.

Imagine ça:

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

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

La référence au nom de la propriété est simplement perdue dans ce processus.

0
Scott Sauyet

Je le préfère propre et simple comme ça:

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
}
0
Maximilian Fixl

Vous pouvez créer une méthode de nommage pour l'objet. La méthode devra muter l'objet afin que les chaînes deviennent un objet contenant deux propriétés, une value et un _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'

Alors maintenant, vous pouvez faire:

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

extPort.postMessage(o);
0
David Hellsing