【问题标题】:JavaScript getter for all properties所有属性的 JavaScript getter
【发布时间】:2010-11-02 21:48:57
【问题描述】:

长话短说:我现在想要一个 PHP 风格的 getter,但在 JavaScript 中。

我的 JavaScript 仅在 Firefox 中运行,因此我可以使用 Mozilla 特定的 JS。

我能找到制作 JS getter 的唯一方法是指定它的名称,但我想为 所有 可能的名称定义一个 getter。我不确定这是否可能,但我非常想知道。

【问题讨论】:

  • 我想他指的是魔术函数 __get 和 __set

标签: javascript firefox getter


【解决方案1】:

Proxy可以!我很高兴这存在!这里给出了答案:Is there a javascript equivalent of python's __getattr__ method?。用我自己的话说:

var x = new Proxy({}, {
  get(target, name) {
    return "Its hilarious you think I have " + name
  }
})

console.log(x.hair) // logs: "Its hilarious you think I have hair"

代表胜利!查看 MDN 文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

适用于 chrome、firefox 和 node.js。缺点:在 IE 中不起作用 - 该死的 IE。很快。

【讨论】:

  • 它也适用于 Edge。具体浏览器版本见caniuse.com
  • 但是如果我想模仿一个函数调用,比如 myProxy.foo('bar')。我已经看到有申请函数但不允许使用自定义名称,总是在代理上执行:myProxy('bar'),我们可以用 myProxy('foo', 'bar') 来模仿它,但后来我们缺少神奇的东西
  • @Enrique 如果你从 getter 返回一个函数,你绝对可以调用myProxy.foo('bar')
  • 我知道这个问题的答案是正确的,但是对于像我这样想要默认返回值的读者,请注意代理优先。
  • @BarryMcNamara 你能澄清一下你的意思是代理优先吗?
【解决方案2】:

如果你在 ES6 中编码,你可以结合代理和类来获得一个漂亮的代码,比如 php

class Magic {
    constructor () {
        return new Proxy(this, this);
    }
    get (target, prop) {
        return this[prop] || 'MAGIC';
    }
}

this 绑定到处理程序,因此您可以使用 this 代替 target。

注意:与 PHP 不同,代理处理所有的属性请求。

let magic = new Magic();
magic.foo = 'NOT MAGIC';
console.log(magic.foo); // NOT MAGIC
console.log(magic.bar); // MAGIC

您可以查看哪些浏览器支持代理http://caniuse.com/#feat=proxy 和类http://caniuse.com/#feat=es6-class。 Node 8 支持两者。

【讨论】:

  • 这是我找到的最佳答案。
  • ^ 这是天才
  • 不需要在代理中为分配实现“set”吗?
  • @Enrique 不,它像普通对象一样工作,但你可以定义它。
【解决方案3】:

您能找到的最接近的是__noSuchMethod__,它相当于 JavaScript 的 PHP 的 __call()。

不幸的是,没有 __get/__set 等价物,这很可惜,因为有了它们我们可以实现 __noSuchMethod__,但我还没有看到使用 __noSuchMethod__ 实现属性(如在 C# 中)的方法。

var foo = {
    __noSuchMethod__ : function(id, args) {
        alert(id);
        alert(args);
    }
};

foo.bar(1, 2);

【讨论】:

  • @Towa Proxy 确实是未来。如果您在“about:flags”下启用实验性 JavaScript 功能,它可以在 Chrome 上使用。 __noSuchMethod__ 没有其他等价物。
  • noSuchMethod 是非标准的,没有任何版本的 Internet Explorer 支持它,因此它可能不适用于您的许多用户的浏览器。
  • ECMAScript 的类似物怎么样?
  • 重要提示: 链接现在显示:此功能已过时。尽管它在某些浏览器中可能仍然有效,但不鼓励使用它,因为它可能随时被删除。尽量避免使用它。
  • 虽然 noSuchMethod 已被删除,但 ECMAScript 2015 (ES6) 规范具有代理对象,您可以使用它实现以下(以及更多)。
【解决方案4】:

Javascript 1.5 确实有 getter/setter syntactic sugar。 John Resig here 解释得很好

它对于网络使用来说不够通用,但 Firefox 肯定有它们(如果你想在服务器端使用它,还有 Rhino)。

【讨论】:

  • 不完全是 __get() 和 __set()。 PHP 版本让您可以监控所有属性,甚至是尚未创建的属性。
【解决方案5】:

如果您真的需要一个有效的实现,您可以通过针对undefined 测试第二个参数来“欺骗”您的方式,这也意味着您可以使用 get 来实际设置参数。

var foo = {
    args: {},

    __noSuchMethod__ : function(id, args) {
        if(args === undefined) {
            return this.args[id] === undefined ? this[id] : this.args[id]
        }

        if(this[id] === undefined) {
            this.args[id] = args;
        } else {
            this[id] = args;
        }
    }
};

【讨论】:

    【解决方案6】:

    如果您正在寻找类似 PHP 的 __get() 函数的东西,我认为 Javascript 不提供任何此类构造。

    我能想到的最好的做法是遍历对象的非函数成员,然后为每个成员创建一个相应的“getXYZ()”函数。

    在狡猾的伪代码中:

    for (o in this) {
        if (this.hasOwnProperty(o)) {
            this['get_' + o] = function() {
                // return this.o -- but you'll need to create a closure to
                // keep the correct reference to "o"
            };
        }
    }
    

    【讨论】:

      【解决方案7】:

      我最终使用了 nickfs 的答案来构建我自己的解决方案。我的解决方案将自动为所有属性创建 get_{propname} 和 set_{propname} 函数。它会在添加函数之前检查函数是否已经存在。这允许您使用我们自己的实现覆盖默认的 get 或 set 方法,而不会有被覆盖的风险。

      for (o in this) {
              if (this.hasOwnProperty(o)) {
                  var creategetter = (typeof this['get_' + o] !== 'function');
                  var createsetter = (typeof this['set_' + o] !== 'function');
                  (function () {
                      var propname = o;
                      if (creategetter) {
                          self['get_' + propname] = function () {
                              return self[propname];
                          };
                      }
                      if (createsetter) {
                          self['set_' + propname] = function (val) {
                              self[propname] = val;
                          };
                      }
                  })();
              }
          }
      

      【讨论】:

        【解决方案8】:

        这并不完全是对原始问题的回答,但是 thisthis 问题已关闭并重定向到这里,所以我在这里。我希望我能像我一样帮助其他一些来到这里的 JS 新手。

        来自 Python,我一直在寻找与 obj.__getattr__(key)obj.__hasattr__(key) 方法等效的方法。我最终使用的是: obj[key] 代表 getattrobj.hasOwnProperty(key) 代表 hasattr (doc)。

        【讨论】:

          【解决方案9】:

          只需将对象包装在 getter 函数中即可获得类似的结果:

          const getProp = (key) => {
            const dictionary = {
              firstName: 'John',
              lastName: 'Doe',
              age: 42,
              DEFAULT: 'there is no prop like this'
            }
            return (typeof dictionary[key] === 'undefined' ? dictionary.DEFAULT : dictionary[key]);
          }
          
          console.log(getProp('age')) // 42
          
          console.log(getProp('Hello World')) // 'there is no prop like this'

          【讨论】:

            猜你喜欢
            • 2011-10-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-06-30
            • 1970-01-01
            • 2016-02-17
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多