8
var tr={};
tr.SomeThing='SomeThingElse';
console.log(tr.SomeThing); // SomeThingElse
console.log(tr.Other); // undefined

tr.get=function(what){
    if (tr.hasOwnProperty(what)) return tr[what];
    else return what;
};
tr.get('SomeThing') // SomeThingElse
tr.get('Other') // Other

Is there any way to make tr.Other or tr['Other'] and all other undefined properties of the object to return its name instead undefined?

rndm
  • 369
  • 1
  • 2
  • 12
  • No. Why would you want to do that? What's wrong with your get() function? – Bergi Jul 16 '12 at 17:14
  • 'tr' is an object which contains site translation. Sometimes he does not have the required fields – rndm Jul 17 '12 at 06:03
  • OK, although I think a fallback to English (or else) would be better than the message's name :-) Please answer my second question: What's wrong with that get() function? – Bergi Jul 17 '12 at 09:36
  • It is not so pretty :) In code already defined tr['Something'] in many places. – rndm Jul 17 '12 at 12:37

3 Answers3

5

Three solutions:

  • Implement your object as a Proxy, which is designed to do exactly what you want. Yet, it is only a draft and currently only supported in Firefox' Javascript 1.8.5 It was standardised with ES6, but might not yet be available in all environments.

  • Always fill your translation object with a complete set of messages. When creating that "dictionary" (serverside or clientside), always include all needed keys. If no translation exists, you can use a fallback language, the message's name or the string representation of undefined - your choice.

    But a non-existing property should always mean "there is no such message" instead of "no translation available".

  • Use a getter function with a string parameter instead of object properties. That function can look the messages up in an internal dictionary object, and handle misses programmatically.

    I would recommend a map object which is different from the dictionary, to allow "get" and co as message names:

var translate = (function(){
    var dict = {
        something: "somethingelse",
        ...
    };
    return {
        exists: function(name) { return name in dict; },
        get: function(name) { return this.exists(name) ? dict[name] : "undefined"; },
        set: function(name, msg) { dict[name] = msg; }
    };
})();
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
2

You could define a getter for your property, either using object initializers:

var o = {
  a: 7,
  get b() {
    return this.a + 1;
  },
  set c(x) {
    this.a = x / 2;
  }
};

console.log(o.a); // 7
console.log(o.b); // 8 <-- At this point the get b() method is initiated.
o.c = 50;         //   <-- At this point the set c(x) method is initiated
console.log(o.a); // 25

or using Object.defineProperties():

var o = { a: 0 };

Object.defineProperties(o, {
    'b': { get: function() { return this.a + 1; } },
    'c': { set: function(x) { this.a = x / 2; } }
});

o.c = 10; // Runs the setter, which assigns 10 / 2 (5) to the 'a' property
console.log(o.b); // Runs the getter, which yields a + 1 or 6
lanzz
  • 42,060
  • 10
  • 89
  • 98
  • It is deprecated and non-standard, and do not solves my problem – rndm Jul 16 '12 at 13:08
  • 1
    Only `Object.prototype.__defineGetter__()` is deprecated. `Object.defineProperty()` and `{ get propName(){} }` are standard and not deprecated. As you have stated it, your question can be solved with getters. You have asked for a specific property (`Other`) to return its name if undefined, are you instead asking for _any_ property of the object to return its name? If so, update your question. – lanzz Jul 16 '12 at 13:48
  • Yes, I need or any property of the object to return its name – rndm Jul 16 '12 at 16:57
  • 1
    In this case you're going to need [Proxies](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Proxy), which are _even less_ standard, _very_ unsupported, and likely to change in incompatible ways in the future. – lanzz Jul 16 '12 at 21:11
  • Thank you for help. May be I will use get() function – rndm Jul 17 '12 at 12:38
  • @Ianzz The link in your answer is broken. – Alan Evangelista Jul 29 '21 at 14:01
  • 1
    @AlanEvangelista Thanks, I've updated the link and included some of the MDN examples in the answer directly. – lanzz Aug 10 '21 at 13:25
1

While this solution isn't exactly what you were looking for, a JavaScript implementation of python's collections.defaultdict class might help:

var collections = require('pycollections');
var dd = new collections.DefaultDict([].constructor);
console.log(dd.get('missing'));  // []
dd.get(123).push('yay!');
console.log(dd.items()); // [['missing', []], [123, ['yay!']]]