我有两个需要的模块:
state.js
define(function () {
var stateObj = {hello:"test!"};
return {
getObj: function () {
return stateObj;
}
};
});
main.js
define(['state'],function (global) {
var privateFn = global.getObj()
return {
getHello: function () {
if(privateFn.hello == "test!")
//do someoperation
},
changeState : function() {
//changes the privateFn state
}
};
});
state
模块将对象提供给main
模块,用于内部状态存储。为main
内部状态保留单独模块的原因是为了便于测试,因此在我的测试用例中,我可以注入一个假state
模块并检查main
的方式}模块工作。
由于我是js world的新手,我在这里采取的方法是否正确,我不确定。
答案 0 :(得分:1)
如果你有一个downvote,那么可能是因为很难以一种明确的方式回答。事实上,我正在查看代码,甚至不确定你在问什么。以下是我的一些想法,但要注意其他人可能非常不同意。
你的州是一个单身人士,所以应该很容易测试。假设您上面的changeState
方法如下所示:
changeState: function (key, value) {
privateFn[key] = value;
}
然后,您可以通过同时包含state
和main
对其进行测试,然后调用main.changeState
并查看state
是否按预期更新:
main.changeState('foo', 'bar');
expect(state.foo).toBe('bar');
执行此操作的其他方法(如果state
不是单例),实际上是在main
上公开状态。这通常通过在前缀下加下划线来完成,因此它被认为是私有的(命名约定,它实际上不是私有的)。然后,在您的测试中,您可以“欺骗”并直接查看状态。
main.changeState('foo', 'bar');
expect(main._state.foo).toBe('bar');
另一种方式是通过依赖注入(这在角度世界中很流行)。这意味着main
需要是某种类型的工厂或类。如果你来自一个java世界,那么一个类可能最有意义:
// Some other file where both main.js and state.js is imported
var main = new Main({
state: state
});
因此main.js
不会自行导入任何内容。
我希望这能回答你的问题。
虽然我正在打字(打字):小心你的命名。 global
通常是指window
(root
也是如此),因此让global
提及您的州是非常令人困惑的。赋予它相同的名称:state
。此外,您的privateFn
指的是一个对象,而不是一个函数(正如Fn
后缀所暗示的那样)。也令人困惑。
我不确定每个人都会同意我的第三件事是“国家”应该指的是国家本身。它在这里是一个包装器。有点像BackboneJS的Model
(其中attributes
就是我所说的state
)。区分这两者很重要:
实际数据通常(如果不是总是)可以转换为JSON并发送存储在服务器上。与Java不同(我认为?),您的状态应该始终容易与其类/包装器分离。包装器可以(应该)依赖于数据,但数据绝对不应该依赖于它的包装器。
修改强>
我刚刚意识到,也许你的意思是main.js
是数据的包装器(也是唯一的包装器)。如果是这种情况,那么我将以不同的方式构建它。我只有一个文件。类似的东西:
function modelFactory (options) {
var state = options.state || {};
// Useful methods...
return {
get: function (key) {
return state[key];
},
set: function (key, value) {
state[key] = value;
// Maybe trigger some change event for others to listen for
},
toJSON: function () {
return JSON.stringify(state);
}
// ...
}
}
然后测试它,你可以做到
var model = modelFactory({
state: {foo: 'bar'}
});
expect(model.get('foo')).toBe('bar');
model.set('hello', 'world');
expect(model.get('hello')).toBe('world');
我上面描述的是Backbone.Model
。