6

我正在尝试解决最近想到的一个问题。假设我们想要并且知道如何在 javascript 中使用动态 getter 和 setter,更像是 php (__get, __set) 中的那些。但是由于 javascript 没有包罗万象的属性,我们唯一能做的就是提供可能的键列表并迭代以仅在这些键上添加 getter 和 setter,并希望不会有其他键出现。

但问题远未解决。因此,我想到的下一个方法是对 and 使用讨厌的 hack trycatch因此任何时候在对象中未定义名称以将其catch用作吸气剂(至少)然后恢复代码,这很难而且可能毫无意义做。但是从这里出现了我的第二个问题,在这样的用途中:

console.log(g.someundefinedproperty); 

结果将是对console.log显示的调用undefined,没有任何异常被抛出。然后我想到了:如果我使用原始的window.undefinedgetter 和 setter 怎么办,毕竟每次我搞砸并拼错单词或其他东西时都必须调用它。

所以我尝试了

Object.defineProperty(window, 'undefined', {
    get : function ()
    {
         // functional code, including getting the caller and figuring out
         // where we are, and what we have to do... easy :D

         console.log('works');
    },
    set : function ()
    {
         // some couple more fine hacks here
         console.log('this too');
    }
});

但不幸的undefined是 window 的属性是configurable : false. 尝试的其他黑客攻击是克隆window对象,除了undefined和内部window属性。并在新对象上定义新的undefined(请注意讽刺)然后window = mybetterwindow;

由于这没有引起任何问题,我寄予厚望,但系统又一次让我失望window,因为设计无法覆盖。我猜测它有自己的吸气剂,它会根据原型中的原型重新实例化自己,window.prototype甚至更好Window.prototype(注意大写)。

作为我在这个实验中的最后一步,我重新定义undefined了这个原型命中运行。无济于事,没有任何改变......我尝试创建一个new Window(),但Window不是构造函数,失败!

由于我的想法已经用完了,我发现自己在这里写这篇请求帮助。如果您有任何想法如何解决动态 getter 和 setter 问题,(the existencial problem of life, universe and everything else),以一种不会以任何方式修改...我使用对象的方式(作为奖励,它不在中need to break)或语法,我恳求你说话或永远保持沉默:)。holefabric of time and space

4

2 回答 2

5

但不幸的是 window 的未定义属性是configurable: false

这仅在EcmaScript 5.1之后才成立。以前,它是可覆盖的。

如果我使用原始的window.undefinedgetter 和 setter 会怎样,毕竟每次我搞砸并拼错单词或其他东西时都必须调用它。

不,那是行不通的。未定义和全局变量“未定义”之间存在差异。每次遇到未定义的值(例如 in typeof (void 0))时,不会评估该变量,仅当您显式使用它时(例如 in g.someprop === undefined)。

任何想法如何解决动态 getter 和 setter 问题?

只有一个解决方案:Proxies. 不幸的是,它只是一个和谐草案,目前仅在 Firefox 的 Javascript 1.8.5 中支持

另请参阅是否有与 __noSuchMethod__ 特性等效的属性,或者在 JS 中实现它的方法?,检测何时将新属性添加到 Javascript 对象?如何检测何时将属性添加到 JavaScript 对象?它实现了一个轮询解决方案(通过检查更改setInterval)。

对于一个干净的解决方案,您当前必须使用一个显式的 getter 函数,该函数传递属性名称 ( g.get("someundefinedproperty"))。

于 2012-12-12T22:32:06.177 回答
2

您要完成的工作(任何未定义属性的全局 getter)超出了跨浏览器 JavaScript 的范围。

最接近的功能将用于__defineGetter__向所有对象添加特定属性:

var o = Object.prototype;
o.__defineGetter__("testo", function() { return "yo in testo"; });
alert({}.testo);
alert((new Date()).testo);

​http://jsfiddle.net/NLCvs/2/

如果您可以提前预测可能未定义的属性的名称,这可能会很有用。即便如此,为所有对象添加一个可能未定义的属性的访问器也是一种非常笨拙和糟糕的形式。

更好的选择是在可能访问未定义的属性时重构代码:

function getter(o, n) {
 return typeof o[n] == 'undefined' ? 'some default value' : o[n];
}
var obj = { hello: 'world' };
alert(getter(obj, 'hello'));
alert(getter(obj, 'an_undefined_property'));

一个更好的选择是使用 mixin 来设置您需要访问的任何默认属性,例如通过jQuery.extend

var defaults = {
 required: 'this property is required'
};
var my_object = {
 something_else: 'this is something else'
};
var o = jQuery.extend({}, defaults, my_object);

// o.required === 'this property is required'
// o.something_else === 'this is something else'
于 2012-12-12T22:33:04.947 回答