扩展或包装本机Date对象

时间:2012-10-05 19:45:27

标签: javascript date coffeescript prototype

我想编写一个围绕Javascript的本地Date对象类型的包装器。对于日期本地的每个属性,我只想将其代理到我的类所拥有的日期。我正在使用咖啡脚本,除了改变日期对象的任何方法之外,一切似乎都有效。我想知道我是否错误地设置了绑定。

这是我到目前为止所拥有的。如果你检查它的内容(修改为与JSLint配合使用,但我在浏览器中看到的行为相同),你可以看到它的行为:http://jsfiddle.net/XRgKM/1/

class CP.MyDate

  @DateProperties: (name for name in Object.getOwnPropertyNames(window.Date.prototype) when _.isFunction(window.Date.prototype[name]))

  constructor: (@date = new Date()) ->
    # Hack to allow me to use the __bind function like the rest of the
    # 'coffeescript native' class functions:
    bnd = `__bind`
    for name in MyDate.DateProperties
      bnd(@[name], @)

    # Validate parameter:
    if not @date instanceof Date
      throw new Error("date must be a native date")

    # Copy date locally:
    @date = new Date(@date)

  test: () => alert("TEST")

  for name in @DateProperties
    MyDate.prototype[name] = () ->
      returnVal = @date[name].apply(@date, arguments)
      if returnVal isnt @date and returnVal instanceof Date
        returnVal = new MyDate(returnVal)
      return returnVal

1 个答案:

答案 0 :(得分:1)

你在循环问题中有标准的闭包。你觉得name会在这里的函数中出现什么?

for name in @DateProperties
  MyDate.prototype[name] = () ->
    returnVal = @date[name].apply(@date, arguments)
    if returnVal isnt @date and returnVal instanceof Date
      returnVal = new MyDate(returnVal)
    return returnVal

在函数内部,name将是@DateProperties的最后一个值,这根本不是你想要的。您需要将name的当前值导入函数而不是name引用。由于这是一个很常见的事情,CoffeeScript有do keyword来帮助:

  

当使用JavaScript循环生成函数时,通常会插入一个闭包装,以确保循环变量被关闭,并且所有生成的函数不只是共享最终值。 CoffeeScript提供do关键字,它立即调用传递的函数,转发任何参数。

你想这样做:

for name in @DateProperties
  do (name) ->
    # Carry on as before...

演示:http://jsfiddle.net/ambiguous/8gc7b/

另请注意,jsfiddle支持CoffeeScript,请在​​侧栏中的 Panels 下查看。

你不需要让DateProperties可见,你可以隐藏它:

class CP.MyDate

  DateProperties = (name for name in Object.getOwnPropertyNames(window.Date.prototype) when _.isFunction(window.Date.prototype[name]))

并参考DateProperties课程中的CP.MyDate