【问题标题】:Javascript proxies: node-proxy, Harmony, mixed objects with magic getters and setters... in Coffeescript?Javascript 代理:节点代理、Harmony、带有魔法 getter 和 setter 的混合对象……在 Coffeescript 中?
【发布时间】:2011-12-08 05:51:01
【问题描述】:

我想要一个带有方法和私有变量的代理对象。

也就是说,所有正常的对象属性:

foo = {}
foo.bar = "baz"
foo.boo = "hoo"

一些原型:

foo.setPrivateThings = function(value){ if (value) private = value; return private; }

枚举跳过私有变量/函数的地方:

console.log(foo); // { bar: "baz", boo: "hoo" }

get/set 将通过一个神奇的 getter/setter 运行:

foo.doesntexist = "..." = function(key){ console.log "Setting "+key; return new Date(); }

到目前为止,我有这个使用节点代理的 hokey Coffeescript。有更好的答案吗?

class Data
    constructor: (obj) ->
        @proxy = require "node-proxy"

        p = @proxy.create
            has: (name) ->
                name of obj
            hasOwn: (name) ->
                ({}).hasOwnProperty.call obj, name
            get: (receiver, name) ->                
                p = obj.transform()[name]
                if typeof p != 'undefined' && p != '__lookupGetter__' && p != '__lookupSetter__'
                    return p()
                # We could do magic getting here
                obj[name]
            set: (receiver, name, val) ->
                # We could do magic setting here
                obj[name] = val
                true
            enumerate: ->
                result = []
                for name of obj
                    result.push name if typeof obj[name] != 'function'
                result
            keys: ->
                Object.keys obj
        , obj

        _transform = {}
        p.transform = (_t) ->
            _transform = _t if _t
            return _transform

        return p


d = new Data
    name: "Bill"
    colors: ["blue", "red"]

d.transform
    timer: ->
        return new Date()

console.log d.name, d.colors, d.timer

console.log d

生产

Bill [ 'blue', 'red' ] Sat, 15 Oct 2011 06:39:27 GMT
{ name: 'Bill', colors: [ 'blue', 'red' ] }

【问题讨论】:

    标签: javascript node.js coffeescript ecmascript-harmony


    【解决方案1】:

    感谢@Raynos,我认为这个解决方案可能是合适的(将进行更多实验):

    obj =
        firstname: "Bill"
        lastname: "Fell"
        colors: ["blue", "red"]
    
    transform =
        name: ->
            "#{this.firstname} #{this.lastname}"
        colorstoo: "colors"
    
    for key, val of transform   
        Object.defineProperty obj, key,
            get: if typeof val == "string" then new Function("return this.#{val}") else val
            enumerable: true
    
    console.log obj.name, obj.colorstoo
    console.log obj
    

    产生:

    Bill Fell [ 'blue', 'red' ]
    
    { firstname: 'Bill',
      lastname: 'Fell',
      colors: [ 'blue', 'red' ],
      name: [Getter],
      colorstoo: [Getter] }
    

    请注意,此解决方案不允许动态获取/设置,只能定义为列表。

    【讨论】:

    • get must be a function or undefinedif typeof val is "string" then get: -> this[val] else value: val?
    • 此外,这一切的意义何在?循环已经通过.hasOwnProperty()for own key, val of obj 防范原型,并且您可以使用模块模式拥有“私有”。
    【解决方案2】:

    枚举跳过私有变量/函数的地方:

    Object.defineProperty(foo, "name", {
      get: function () { "return magic"; },
      set: function (value) { setMagic(value); },
      writable: true,
      configurable: true
      enumerable: false
    });
    

    代理是多余的,只需定义不可枚举的属性

    【讨论】:

    • 谢谢,但我仍然需要神奇的 get() 用于其他用途——这个例子只是为了节省空间。
    • @JarebShubway defineProperty 允许获取和设置。还有 get 和 set 真的很贵,为什么需要呢?
    • 我有一组复杂的数据,我想在访问时根据不同的规则对其进行修改。从示例开始,一个动态的键列表(例如,_transform)表示一些任意规则(例如,return new Date())以在访问时应用。
    猜你喜欢
    • 1970-01-01
    • 2011-10-22
    • 1970-01-01
    • 2018-08-01
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    • 1970-01-01
    • 2018-06-05
    相关资源
    最近更新 更多