Javascript 代理:节点代理、Harmony、具有神奇 getter 和 setter 的混合对象...在 Coffeescript 中?

发布于 2024-12-10 08:22:58 字数 1988 浏览 0 评论 0原文

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

也就是说,所有普通对象属性:

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(); }

到目前为止,我有这个使用节点代理的做作的 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' ] }

I would like to have a proxied object with methods and private variables attached to it.

That is to say, all normal object properties:

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

with some prototypes:

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

where enumeration skips private variables/functions:

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

and get/set will be run through a magic getter/setter:

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

So far I have this hokey Coffeescript using node-proxy. Any better answers?

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

produces

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清浅ˋ旧时光 2024-12-17 08:22:58

其中枚举跳过私有变量/函数:

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

代理太过分了,只需定义不可枚举的属性

where enumeration skips private variables/functions:

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

Proxies are overkill, just define non-enumerable properties

凉世弥音 2024-12-17 08:22:58

感谢@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] }

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

Thanks to @Raynos, I think this solution may be suitable (will experiment more):

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

produces:

Bill Fell [ 'blue', 'red' ]

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

note that this solution doesn't allow for dynamic get/set, only defined as a list.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文