Javascript 为什么相同的摩卡咖啡测试在第一次测试后失败?

Javascript 为什么相同的摩卡咖啡测试在第一次测试后失败?,javascript,testing,coffeescript,bind,mocha.js,Javascript,Testing,Coffeescript,Bind,Mocha.js,我有一个类MyClass,它接受对象作为方法附加到它。这些方法调用MyClass.push将数据添加到对象的内部@\u列表中。两个相同测试用例中的第二个失败,但我不明白为什么: chai = require "chai" chai.should() obj = name: 'foo' f: -> for i in [1..5] @push "Element #{i}" class MyClass constructor: (@options) ->

我有一个类
MyClass
,它接受对象作为方法附加到它。这些方法调用
MyClass.push
将数据添加到对象的内部
@\u列表中。两个相同测试用例中的第二个失败,但我不明白为什么:

chai = require "chai"
chai.should()

obj =
  name: 'foo'
  f: ->
    for i in [1..5]
      @push "Element #{i}"


class MyClass
  constructor: (@options) ->
    @methods = {}
    @_list = []

    if 'attach' of @options
      @attach @options.attach

  push: (m) ->
    @_list.push m

  list: ->
    @_list

  method: (v) ->
    @methods[v].f

  run: (options) ->
    @method('foo')()

  attach: (o) ->
    @methods[o.name] = o
    @methods[o.name].f = o.f.bind(@)

describe 'MyClass', ->
  it 'list should have five elements', ->
    v = new MyClass attach: obj
    v.run()
    v.list().length.should.equal 5
  it 'list should have five elements (#2)', ->
    v = new MyClass attach: obj
    v.run()
    v.list().length.should.equal 5
我相信这与函数绑定有关,因为当我将第二个
v=new MyClass attach:obj
替换为:

v = new MyClass attach:
  name: 'foo'
  f: ->
    for i in [1..5]
      @push "Element #{i}"
两项测试都通过了。但是我不理解这种行为,因为我认为
.bind()
会创建函数的副本。那么这里发生了什么,我如何让这两个测试独立运行呢?

JavaScript(以及coffeescript)对象是通过引用传递的。当您开始第二个测试时,您的
obj
对象已更改,因为您通过执行以下操作修改了其
f
属性:

@methods[o.name].f=o.f.bind(@)

您可以传递它的副本以避免这种情况。

JavaScript(以及coffeescript)对象是通过引用传递的。当您开始第二个测试时,您的
obj
对象已更改,因为您通过执行以下操作修改了其
f
属性:

@methods[o.name].f=o.f.bind(@)


您可以传递一份副本来避免这种情况。

我觉得我应该理解这一点,但我不理解(尽管我正在努力!)。这5个元素设置在
v
,而不是
obj
。我希望将数组保留在每个对象的内部(
v
),但是
obj
(包含函数)需要能够在
MyClass
的不同实例之间共享。这里我假设@push指的是
obj
所附加的
v
。我说得通吗?@user2010963因为
obj
是通过引用传递的,当您通过执行
@methods[o.name]将
o.f
绑定到第一个对象时。f=o.f.bind(@)
您正在更改obj。这是您的代码更正。另外,我很抱歉,我最初的回答是错误的。我觉得我应该理解这一点,但我不理解(尽管我正在努力!)。这5个元素设置在
v
,而不是
obj
。我希望将数组保留在每个对象的内部(
v
),但是
obj
(包含函数)需要能够在
MyClass
的不同实例之间共享。这里我假设@push指的是
obj
所附加的
v
。我说得通吗?@user2010963因为
obj
是通过引用传递的,当您通过执行
@methods[o.name]将
o.f
绑定到第一个对象时。f=o.f.bind(@)
您正在更改obj。这是您的代码更正。另外,我很抱歉,我最初的回答是错误的。