Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/410.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 以字符串形式获取对象属性名称_Javascript_String_Object_Properties - Fatal编程技术网

Javascript 以字符串形式获取对象属性名称

Javascript 以字符串形式获取对象属性名称,javascript,string,object,properties,Javascript,String,Object,Properties,是否可以将对象属性名称作为字符串获取 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

是否可以将对象属性名称作为字符串获取

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'
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
}
注意:此代码正是我要查找的代码。我知道这听起来很愚蠢,但事实并非如此

这就是我想用它做的

HTML

----------------------回答-----------------------

多亏了ibu。他指出了正确的方向,我使用了递归函数

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'

演示:

是的,您可以,只要稍作改动

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";
注意我不确定它可以用来做什么

其他注意事项无法很好地处理嵌套对象。但是,再一次,请看第一个注释。

不,这是不可能的

想象一下:

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

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

在该过程中,对属性名称的引用将丢失。

您可以为对象创建名称空间方法。该方法将需要对对象进行变异,使字符串成为一个对象,而不是保存两个属性,一个
和一个
\u名称空间

演示:

现在你可以做:

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

extPort.postMessage(o);

您可以将属性包装在函数中,然后将函数转换为字符串并从中提取属性

例如:

function getPropertyName(propertyFunction) {
    return /\.([^\.;]+);?\s*\}$/.exec(propertyFunction.toString())[1];
}
然后使用它:

var myObj = {
    myProperty: "testing"
};

getPropertyName(function() { myObj.myProperty; }); // myProperty
小心,迷你们可能会打破这一点


编辑:我创建了一个编译器转换,可以与babel和typescript编译器一起使用(请参阅)。这比在运行时做某事要可靠得多。

我知道一个最佳实践是使用。它将为您解析为数组属性名。例如:

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

我希望这个例子对你有用。

我也有同样的情况

以下是您使用或库完成此任务的方法,但有一个价值限制是唯一的:

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 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'

我更喜欢这样干净简单:

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

我参加聚会迟到了,但我采取了完全不同的方法,所以我会加入我的方法,看看社区怎么想

我过去想干什么就干什么。 我的属性是调用时返回属性值的函数,我可以使用
.name

以下是一个例子:

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

console.log( myObject.a.key )
person = {
    firstName(){
        return 'John';
    },
    address(){
        return '123 street'
    }
}

person.firstName.name // 'firstName'
person.address.name // 'address'
注意:
在这种情况下,您无法在运行时轻松更改属性(例如firstname)的值。 您需要创建一个函数(
.name
在本例中是匿名的),该函数将返回一个新的命名函数,该函数将返回新值:

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

根据@David Sherret的ES6答案,可以将其变得非常简单:

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

var-propName=(obj)=>新代理(obj{
获取(\ u0,键){
返回键;
} 
});
var person={};
person.first_name='Jack';
person.last_name='Trades';
person.address={};
person.address.street='Factory 1';
person.address.country='美国';
console.log(propName(person.first_name);

console.log(propName(person.address).country)我喜欢单行程序,这里有一个通用的解决方案:

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

propName(person, person.age)

我在TypeScript中使用以下内容。这种方式保留类型信息,不允许选择不存在的属性键

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)
}
导出函数getPropertyName(obj:T,选择器:(x:Record)=>keyof T:keyof T{
const keyRecord=Object.keys(obj).reduce((res,key)=>{
const typedKey=作为T键的键
res[typedKey]=typedKey
返回res
},{}作为记录)
返回选择器(键记录)
}

如果有人在寻找MarsRobot答案的打字脚本版本,请尝试以下方法:

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

即使对象具有多个具有相同值的属性(与上面的一些其他答案不同),此版本也可以使用,并且当您到达此处时,Visual Studio等编辑器将为属性名称提供智能感知:
nameof(obj,x=>x.

我很困惑…为什么您希望属性名返回与您输入的内容相同的内容?那么您已经知道属性名了…如果您正在寻找迭代属性的方法,您可以使用括号表示法并循环键,因为属性也是散列指示符您还需要传递对属性引用的字符串不知道有关
地址
对象的任何信息,而
地址
属性引用的对象也不知道有关
个人
对象的任何信息。我知道这可能会让人困惑,但这正是我所说的ed.我需要属性名作为字符串-1抱歉,您的代码实际上是一个错误的做法。请参见此示例:…并作为参考;-)这假设一个对象中没有两个属性具有相同的值。如果传递person.first\u name,则函数返回'first\u name',但如果使用person.address.street,则返回false。可能是递归使用它?我对这个答案很感兴趣,所以我开始尝试破解它,以找到更干净的方法。下面是我想到的到目前为止,你怎么看:@JasonSperske不错,但它不是递归的,所以它只能在3个层次上运行:现在试试:)还有更大的问题,比如它需要所有的值并将它们转换为字符串,但这是一段有趣的代码,它是最好的解决方案!如果您看到关于“无返回值”的警告;这是修改后的版本:Object.keys(obj.map)(k=>{res[k]=()=>k;返回k;});仅供参考,如果有人正在寻找,我已经在下面添加了一个TypeScript版本。@请不要欺负我,因此有这样一句话:“我的属性是调用时返回属性值的函数”然而,在他的例子中,他使用person.firstName='Jack'这是一个字符串…这就是为什么我在回答中说得很清楚:1-我采取了不同的方法,2-我的属性是函数,3-我有一个关于如何更新属性值的说明。
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'