从属性值中获取属性键

时间:2015-11-30 11:15:58

标签: javascript javascript-objects

给出以下javascript对象:

AddressBook.prototype.getPerson = function(id){
    this.last_id = id;
    return this.lisPerson.find(buscarPersona,this);
}
function buscarPersona(element){
    if(element.id === this.last_id){
        return element;
    }else{
        return false;   
    }
}

如何从var commands = { back:{ command: "b", aliases: ["back","go back","backwards"], action: function(){ return this.key; //I want this to return "back" (the prop name) }, desc: "goes back" } }

中访问“返回”的属性名称

我认为它应该非常简单,但如果它不是简单的话,我会添加更多细节。

  • 注意:action()偶然保留了名称,并且未承诺将来或其他命令保留该名称。

编辑: 有时我们会变得复杂,而我们可以很快解决问题。 在这种情况下,我可以继续并返回字符串“返回”

如果有这样的解决方案,我会留下问题并接受解决我问题的答案。

5 个答案:

答案 0 :(得分:2)

当您按以下方式致电action时:

commands.back.action();

action的范围是back。遗憾的是,创建分配给commands.back的对象并不知道this内的action被称为"back"。根据我的理解,这样做是因为我们可以将分配给commands.back的对象分配给另一个具有其他名称的对象。如:

var foo = { f: function(){console.log(this) } };
var bar = foo;
bar.f();

或者更接近你所拥有的......

var foo = {
    bar: {
        f:function(){console.log(this)}
    }
};
var other = { another: (foo.bar) };

我知道对象知道它在哪里创建的名称的唯一方法是函数。因此,我们可以创建一个名为back的临时函数,该函数将根据需要创建一个对象。

var commands = {
    back:(new function back(){
        // I prefer to assign to a variable to assist with the readability as to what "this" is:)
        var self     = this;
        self.command = "b";
        self.aliases = ["back","go back","backwards"];
        self.action  = function(){
            // Can leave as "this" or change to "self".
            return this.key;
        };
        self.desc = "goes back";
        self.key  = self.prototype.constructor.name;
    })
}

最简单的解决方案

但在那时,也可以添加一个已经具有该名称的属性。我建议使用名为keyname的属性,而不是直接将名称放入action函数,以便更容易使用名称的多个位置。此外,如果需要,允许在一个地方更改对象内的名称。

var commands = {
    back:{
        command: "b",
        aliases: ["back","go back","backwards"],
        action: function(){
            return this.key;
        },
        desc: "goes back",
        key: "back"
    }
}

编辑:添加此编辑作为另一种方式,但我仍然会采用上一种方式。我们可以使用Object.keys来获取属性的名称,因为back被添加为commands的可枚举属性。

var i        = 0,
    commands = { back: {
        key: (function(id){return function(){return Object.keys(commands)[id]}})(i++)
    }}

然后可以通过以下方式获取key

commands.back.key();

或在action函数中:

this.key();

可以将key添加到back作为get,如下所示:

var i        = 0,
    commands = { back: { 
        id: (i++),
        get key() {return Object.keys(commands)[this.id]}
    }}

这样您就可以commands.back.keyaction函数this.key访问该媒体资源。

还可以预先定义所有内容,然后执行以下操作:

var i = 0, commands = { back: undefined };
commands.back = { key: Object.keys(commands)[i++] };

答案 1 :(得分:2)

如上所述,返回字符串绝对是最简单的方法。但我可以看到某些人可能希望能够通过动态创建的对象获得类似功能的情况,其中直到运行时才知道密钥。

在这种情况下可以使用的解决方案是将commands对象暴露给子对象,以便他们可以自我查找:

var commands = {
    back:{
        command: "b",
        aliases: ["back","go back","backwards"],
        action: function(){
            var commandKeys = Object.keys(commands);
            for(var i=0; i < commandKeys.length; i++){
                if(commands[commandKeys[i]] === this){
                    return commandKeys[i];
                }
            }
        },
        desc: "goes back"
    }
};

在这种情况下,在所有这些操作对象之间共享函数也可能更有意义:

var commands = {
    back:{
        command: "b",
        aliases: ["back","go back","backwards"],
        action: getAction,
        desc: "goes back"
    },
    forward: {
        //...
        action: getAction,
        //...
    }
};

function getAction() {
    var commandKeys = Object.keys(commands);
    for(var i=0; i < commandKeys.length; i++){
        if(commands[commandKeys[i]] === this){
            return commandKeys[i];
        }
    }
}

除非您需要为每个子对象执行某些特定逻辑。

编辑:为了提高效率,我们可以将其设置为每次调用都不执行getAction函数并添加将存储名称的属性。这样,查找仅在第一次发生。

var commands = {
    back:{
        command: "b",
        aliases: ["back","go back","backwards"],
        action: getAction,
        desc: "goes back"
    },
    forward: {
        //...
        action: getAction,
        //...
    }
};
// Only needs to getKey the first time called.
function getAction() {
    if(!this.key) this.key = getKey(this);
    return this.key;
}
function getKey(obj) {
    var commandKeys = Object.keys(commands);
    for(var i=0; i < commandKeys.length; i++){
        if(commands[commandKeys[i]] === obj){
            return commandKeys[i];
        }
    }
}

答案 2 :(得分:1)

您可以添加并建议为您的每个对象添加toString方法。

var commands = {
back:{
    command: "b",
    name : "back",
    aliases: ["back","go back","backwards"],
    action: function(){
        return this.toString(); 
    },
    desc: "goes back",
    toString : function(){
      return this.name;
    }
 }
}
console.log(commands.back.action()); // back
console.log(commands.back.toString()); // back

答案 3 :(得分:1)

您在这里所拥有的是一个嵌套对象,保存在对象的属性上。

你无法手工获取该属性 - 除非你正在做一些奇怪的元编程工作,例如获取AST父节点并尝试确定对象被保持的属性等。最简单的方法是保存属性名称使用字符串即:&#34;返回&#34;。

简单来说,就像将对象保存到var

var obj = {/*....*/};

您正试图从对象中获取var名称。

请记住,在JavaScript中,您可以使用字符串和索引表示法访问对象属性,因此也可以使用commands.back调用commands['back']。如果我猜对了,你正试图进行一种调度,所以这种符号对你有用。

答案 4 :(得分:0)

如果您已获得该对象(文字对象),则无法使用this关键字。你有两个解决方案:

   return commands.back.aliases[0]

或者,您可以将对象构造为原型对象而不是文字对象:

var commands = function() {

  this.back = function() {
    this.command = "b";
    this.aliases = ["back","go back","backwards"];
    this.action = function() {
      return this.aliases[0];
    };
    this.desc = "goes back";
  };
};

并像这样初始化

var instance = new commands();
instance.action(); // it returns "back" string