在读取之前设置未定义的 javascript 属性

问题描述 投票:0回答:4
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

有没有办法让 tr.Other 或 tr['Other'] 以及对象的所有其他未定义属性返回其名称而不是未定义?

javascript object getter
4个回答
5
投票

三种解决方案:

  • 将您的对象实现为

    Proxy
    ,它旨在完全执行您想要的操作。 然而,它只是一个草案,目前仅 在 Firefox 的 Javascript 1.8.5 中受支持 它已通过 ES6 进行标准化,但可能尚未在所有环境中可用。

  • 始终用一组完整的消息填充您的翻译对象。创建“字典”(服务器端或客户端)时,请始终包含所有需要的键。如果不存在翻译,您可以使用后备语言、消息名称或

    undefined
    的字符串表示形式 - 您的选择。

    但是不存在的属性应该始终意味着“没有这样的消息”而不是“没有可用的翻译”。

  • 使用带有字符串参数的 getter 函数而不是对象属性。该函数可以在内部字典对象中查找消息,并以编程方式处理未命中的消息。

    我会推荐一个与字典不同的地图对象,以允许“get”和co作为消息名称:

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

2
投票

您可以使用对象初始值设定项为您的属性定义 getter

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

或使用

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

1
投票

虽然这个解决方案并不完全是您想要的,但Python的collections.defaultdict类的JavaScript实现可能会有所帮助:

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

0
投票

代理:

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"

这主要用于测试原因,当您有一个大/旧的代码并且甚至不知道可能需要哪些键时。

如果您从头开始编码,使用代理可能是糟糕设计的标志(它在幕后工作,读者或未来的您可能不清楚),最好使用(作为选项)直接函数

.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"

您输入的内容多了一点,但为将来节省了很多时间,当您尝试找出发生了什么时。

© www.soinside.com 2019 - 2024. All rights reserved.