【问题标题】:How can I define a default getter and setter using ECMAScript 5?如何使用 ECMAScript 5 定义默认的 getter 和 setter?
【发布时间】:2010-06-24 18:20:50
【问题描述】:

如何为原型指定默认 getter? 默认 getter 是指在调用 obj.undefinedProperty123 时调用的函数。

我试过 Object.prototype.get = function(property) {..} 但在这种情况下没有调用它。

【问题讨论】:

  • 我认为即使使用任何非标准实现也没有办法做到这一点,当然也不能使用 ECMAScript 5。Firefox 中的方法有一个名为 __noSuchMethod__ 的非标准实现,并且可能会出现在 Chrome 上,但对于非函数属性则没有类似的东西。唯一的途径似乎是使用包装函数,例如get,通过它可以访问所有属性。

标签: javascript prototype getter ecmascript-5


【解决方案1】:

在 ECMAScript 5 中,您只能通过 Object.defineProperty 拦截特定命名属性(并非所有属性)的 get/set 操作:

Object.defineProperty(someObj, "someProp", {
    get: function() {
        console.log("you tried to get someObj.someProp");
        return "foo";
    }
});

在这里,get 函数将在代码尝试读取 someObj.someProp 时运行。

在即将到来的 ECMAScript 6 草案中,这将通过 proxies 实现。代理具有底层目标对象和设置/获取功能。任何时候在任何代理的属性上发生 set 或 get 操作时,相应的函数都会运行,将代理的目标对象、使用的属性名称和 set 尝试中使用的值作为参数。

var proxyHandler = {
    get: function(obj, name){
        console.log("you're getting property " + name);
        return target[name];
    },
    set: function(obj, name, value) {
        console.log("you're setting property " + name);
        target[name] = value;
    }
}

var underlyingObj = {};

// use prox instead of underlyingObj to use get/set interceptor functions
var prox = new Proxy(underlyingObj, proxyHandler);

在这里,设置为获取prox 上的属性值将导致set/get 函数运行。

【讨论】:

    【解决方案2】:

    Gareth 说了什么,除了__noSuchMethod__

    或者您可能正在考虑 PHP?

    这是一篇关于最近标准化的属性 getter/setter 的非常好的文章,重点介绍了一些以前的非标准化身。

    http://whereswalden.com/2010/04/16/more-spidermonkey-changes-ancient-esoteric-very-rarely-used-syntax-for-creating-getters-and-setters-is-being-removed/

    总结:目前还没有标准的“包罗万象”的 getter / setter,但 Object.defineProperty 是未来。

    【讨论】:

      【解决方案3】:

      您需要等待 ECMA6“代理”系统的实施,该系统旨在执行此操作。见http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies

      【讨论】:

        【解决方案4】:

        你想创建一个Proxy

        const data = {};
        
        const proxy = new Proxy(data, {
          get: (target, prop) => {
            console.log({ target, prop });
            return "My Value";
          },
          set: (target, prop, value) => {
            console.log({ target, prop, value });
            return true;
          },
        });
        
        proxy["foo"] = "bar";
        const bar = proxy["foo"];
        

        【讨论】:

          【解决方案5】:

          Firefox 可以使用非标准的 noSuchMethod:-

          ({__noSuchMethod__:function(){alert(1);}}).a();
          

          【讨论】:

            【解决方案6】:

            我不确定你在问什么。但是,如果您希望在用户尝试访问时调用方法 object.nonExistingProperty 。我不认为有任何方法可以做到这一点。

            【讨论】:

            • 这正是我想做的。我认为这是可能的,我想我记得我以前做过 - 如果我知道如何......
            【解决方案7】:

            也许迟到了,让我们添加简单的 ES5 友好的“类创建”:字符串道具和吸气剂 - 我需要它来进行一些古老的重写,以暂时支持 IE(是的,这很痛苦,仍然发现有人依赖 ActiveX )

            var MyObj = function () {
              var obj = {
                url: 'aabbcc',
                a: function(){ return this.url;}
              }  
              Object.defineProperty(obj, "urltoo", { get: function () { return this.url; } })
              return obj;
            }
            
            var X = new MyObj();
            x.url // aabbcc
            x.urltoo // aabbcc
            x.urltoo() // error - not a function
            x.a() // aabbcc
            x.a // ƒ (){ return this.url;}
            

            【讨论】:

              【解决方案8】:

              我遇到这个问题是因为我想要这种行为:如果对象属性未定义,则返回一些默认值。

              const options = {
                foo: 'foo',
                bar: 'bar',
                baz: 'baz'
              };
              
              function useOptionValue(optionName) {
                // I want `options` to return a default value if `optionName` does not exist
                const value = options[optionName];
                // etc...
              }
              

              执行此操作的简单方法(对于此用例没有 Proxy 或 Object.defineProperty 过度杀伤)如下所示:

              function useOptionValue(optionName) {
                const value = options[optionName] || defaultValue;
              }
              

              或者,如果你想变得花哨,你可以使用Symbol

              const default = Symbol.for('default');
              
              const options = {
                foo: 'foo',
                bar: 'bar',
                baz: 'baz',
                [default]: 'foobarbaz'
              };
              
              function useOptionValue(optionName) {
                const value = options[optionName] || options[default];
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-03-29
                • 2019-10-18
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-02-19
                相关资源
                最近更新 更多