When you call action like this:
commands.back.action();
the scope of action is back . Unfortunately, creating an object that is assigned to commands.back does not know that this inside the action is called "back" . In my opinion, this is done because we can assign the object assigned to commands.back another object with a different name. How in:
var foo = { f: function(){console.log(this) } }; var bar = foo; bar.f();
Or closer to what you have ...
var foo = { bar: { f:function(){console.log(this)} } }; var other = { another: (foo.bar) };
The only way to find out where the object knows the name of what it was created inside is through functions. Thus, we can create a temporary function called back that will create the object as desired.
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; }) }
Simplest solution
But at this point, you can simply add a property that already has a name. I would recommend making a property with the name key or name instead of putting the name directly in the action function, so that it is easier to have several places where the name is used. In addition, if necessary, there may be a place for changing the name inside the object.
var commands = { back:{ command: "b", aliases: ["back","go back","backwards"], action: function(){ return this.key; }, desc: "goes back", key: "back" } }
EDIT: Added this edit as another way to do this, but I will still do the previous path. We can use Object.keys to get the property name, since back added as an enumerated property of commands .
var i = 0, commands = { back: { key: (function(id){return function(){return Object.keys(commands)[id]}})(i++) }}
Then you can get key as follows:
commands.back.key();
Or in the action function:
this.key();
You can add key to the back as get , which will look like this:
var i = 0, commands = { back: { id: (i++), get key() {return Object.keys(commands)[this.id]} }}
This will allow you to access the property as commands.back.key and in the action function as this.key .
You can also predefine everything, and then do the following:
var i = 0, commands = { back: undefined }; commands.back = { key: Object.keys(commands)[i++] };