我有一个类MyClass
,它接受作为方法附加到它的对象。这些方法调用MyClass.push
将数据添加到对象的内部@_list
数组中。两个完全相同的测试用例中的第二个失败了,但我不明白为什么:
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()
创建了该函数的副本。那么这里发生了什么,以及如何让两个测试独立运行?
答案 0 :(得分:1)
JavaScript(以及coffeescript)对象通过引用传递。当您开始第二次测试时,您的obj
对象已更改,因为您通过执行以下操作修改了其f
属性:
@methods[o.name].f = o.f.bind(@)
您可以传递它的副本以避免这种情况。