在对象上定义getter,以便所有未定义的属性查找返回“”

时间:2012-05-23 21:08:26

标签: javascript node.js

基本上我需要能够做到这一点:

var obj = {"foo":"bar"},
    arr = [];
with( obj ){
   arr.push( foo );
   arr.push( notDefinedOnObj ); // fails with 'ReferenceError: notDefinedOnObj is not defined'
}
console.log(arr); // ["bar", ""] <- this is what it should be.

我正在寻找一个“全局”等价的{}.__defineGetter__{get},以便为所有未定义的属性getter返回一个空字符串(请注意,这与{{{}的属性不同1}})。

4 个答案:

答案 0 :(得分:9)

只要访问未定义的属性,就可以创建Proxy以返回空字符串。

app.js

var obj = {"foo":"bar"},
    arr = [],
    p = Proxy.create({
        get: function(proxy, name) {
            return obj[name] === undefined ? '' : obj[name];
        }
    });
arr.push( p.foo );
arr.push( p.notDefinedOnObj );

console.log(arr);

正如问题作者David Murdoch指出的那样,如果您使用的是节点v0.6.18(编写本文时的最新稳定版本),则必须在运行脚本时传递--harmony_proxies选项:

$ node --harmony_proxies app.js
[ 'bar', '' ]

请注意,如果您使用with,此解决方案将,如:

var obj = {"foo":"bar"},
    arr = [],
    p = Proxy.create({
        get: function(proxy, name) {
            return obj[name] === undefined ? '' : obj[name];
        }
    });
with ( p ) {
   arr.push( foo ); // ReferenceError: foo is not defined
   arr.push( notDefinedOnObj );
}

console.log(arr);
将代理添加到范围链时,

with似乎没有调用代理的get方法。

注意:传递给Proxy.create()的代理处理程序就是不完整。有关详细信息,请参阅Proxy: Common mistakes and misunderstanding

答案 1 :(得分:3)

javascript中没有全局缺失的成员处理程序。您需要引入一个函数来抽象出行为

function getOrEmpty(obj, name) {
  if (!obj.hasOwnProperty(name)) {
    return "";
  }
  return obj[name];
}

var obj = {"foo":"bar"},
    arr = [];
arr.push(getOrEmpty(obj, "foo"));
arr.push(getOrEmpty(obj, "someUndefinedProperty"));
console.log(arr);

答案 2 :(得分:1)

使用ES6及更高版本,您可以使用代理,就像建议的接受答案一样。但是如果你被ES5困住,这就是答案。

使用ES5,你必须创建自己的类,就像在这个简单的例子中一样

function StrictObject() {
  var values = Object.create(null);
  this.set = function (key, value) {
    values[key] = value;
  };
  this.get = function (key) {
    if (!(key in values)) {
      throw new Error("Could not find " + key);
    }
    return values[key];
  };
}
var obj = new StrictObject();

obj.set('dad', 'homer');
console.log(obj.get('dad'));    // homer
console.log(obj.get('uncle'));  // throws error

答案 3 :(得分:1)

Proxy.create似乎不再是一件事。

这是一个新的例子:

&#13;
&#13;
const p = new Proxy({foo:1}, {
    get(obj, name) {
        return Object.hasOwnProperty.call(obj, name) ? obj[name] : '';
    }
})

console.log(p.foo);
console.log(p.bar);
&#13;
&#13;
&#13;

你可以[ab]使用它做一些有趣的小事,比如创建React助手:

const cc = new Proxy(Object.create(null), {
    get(proxy, name) {
        return ({className,...props}) => React.createElement(name, {className: classcat(className), ...props})
    }
})

<cc.tr className={[theme.tr,theme.hrow]}>...</cc.tr>
// renders: <tr class="datatable_tr--2vnM1 datatable_hrow--_PG2G">...</tr>