9
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?

4
  • No. Why would you want to do that? What's wrong with your get() function? Commented Jul 16, 2012 at 17:14
  • 'tr' is an object which contains site translation. Sometimes he does not have the required fields Commented Jul 17, 2012 at 6: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? Commented Jul 17, 2012 at 9:36
  • It is not so pretty :) In code already defined tr['Something'] in many places. Commented Jul 17, 2012 at 12:37

4 Answers 4

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; }
    };
})();
Sign up to request clarification or add additional context in comments.

Comments

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

7 Comments

It is deprecated and non-standard, and do not solves my problem
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.
Yes, I need or any property of the object to return its name
In this case you're going to need Proxies, which are even less standard, very unsupported, and likely to change in incompatible ways in the future.
@AlanEvangelista Thanks, I've updated the link and included some of the MDN examples in the answer directly.
|
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!']]]

Comments

0

Proxy:

let YOUR_OBJECT = {
   key1: 111,
};

/***/
YOUR_OBJECT = new Proxy(YOUR_OBJECT, {

    get(obj_origin, key, obj_proxy) {

        if (!(key in obj_origin)) {
            // console.error(key + ' not found!');
            // throw new Error(key + ' not found!');
            
            return key;
        }

        return Reflect.get(...arguments);
    },
    
});

/***/
console.log(YOUR_OBJECT.key1); // 111
console.log(YOUR_OBJECT.key2); // "key2"

This is useful mainly for testing reasons, when you have a big/old code and don't even know, which keys may be required.

If you're coding from scratch, usage of proxy may be sign of bad design (it's doing work behind the scene, that may be not clear for reader or future you), better to use (as option) direct functions .get(key), .set(key, val)

const obj = {
   _storage: {
       key1: 111,
   },
   
   get: function(key) {
       if (!(key in this._storage)) {
           return key;
       }
       
       return this._storage[key];
   },
   
   set: function(key, val) {
       this._storage[key] = val;   
   },
};

/***/
console.log(obj.get('key1')); // 111
console.log(obj.get('key2')); // "key2"

You are typing a bit more, but saving much time for future, when you will try to figure out, what's going on.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.