是否可以区分结构构建(如继承)和运行时依赖(在方法调用中)所需的依赖项。
一个小例子:
2“班级”:彼此依赖的父亲和孩子
Father.js
define(['Child'], function (Child) {
function Father() {};
Father.prototype.childs = [];
Father.prototype.addChild = function (c) {
if (!(c instanceof Child)) {
alert("nope");
}
}
return Father;
});
Child.js
define(['Father'], function(Father){
function Child(){
this.father = [];
}
Child.prototype.setFather = function(f){
if(!(f instanceof Father)){
alert("false");
}
}
return Child;
});
和 app.js
requirejs(['Child', 'Father'], function(Child, Father){
var c = new Child();
var f = new Father();
c.setFather(f);
f.addChild(c);
});
使用导出时,您只能扩展一个对象(如果我是正确的)。那么有可能建立这样的结构吗?
我真正尝试做的事情:有一个自动的“类”加载(分隔文件),它加载一个更大的模型中的所有依赖项,它具有一些循环依赖项。一些依赖项需要立即(继承),有些只在对象启动后才需要。我无法找到解决问题的好办法。
答案 0 :(得分:2)
这是(IMO)一个多变的有效问题,从昨天开始困惑我。如果我是你,我会考虑优先顺序:
拥抱鸭子。一个有用的$('.element').click(function () {
var offsetTop = $('.destination').offset().top;
$('html,body').stop(true, false).animate({ scrollTop: offsetTop }, 800);
});
类可能有像Child
和play()
这样的方法,所以"如果它像鸭子一样走路而且像鸭子一样嘎嘎叫......"变成"如果它像孩子一样玩耍,像孩子一样哭泣,那么它就是一个孩子":
cry()
这种方法的另一个好处(在一般情况下)是你实际上是在Javascript中使用等效的接口进行编程。即思考过程是"我需要// Father.js
define([], function() {
function Father() {};
Father.prototype.childs = [];
Father.prototype.addChild = function (c) {
if( !c || typeof(c.play) !== 'function' || typeof(c.cry) !== 'function' ) {
alert("nope");
}
}
return Father;
});
为什么? - 播种和哭泣。 - 然后对我来说,我得到的对象有这两种方法就足够了。我不关心它的确切实现。"
这是技术性和丑陋的,但(至少IMO)可以接受的丑陋:你可以引入第三种依赖来打破周期,这与周期一样。即:
Child
捕获:您必须确保从某个地方需要// Father.js
define([], function() {
function Father() {};
Father.prototype.childs = [];
return Father;
});
// Child.js
define(['Father'], function(Father){
function Child(){
this.father = [];
}
Child.prototype.setFather = function(f){
if(!(f instanceof Father)){
alert("false");
}
}
return Child;
});
// FatherAugmentor.js (any ideas for a better name?)
define(['Father', 'Child'], function(Father, Child) {
Father.prototype.addChild = function (c) {
if (!(c instanceof Child)) {
alert("nope");
}
}
});
!或者,您可以使用名称(再次丑陋),以便上面的FatherAugmentor
成为FatherAugmentor
,并将上面的Father
重命名为,例如Father
:
FatherBase
有了这个,你要确保任何人请求// FatherBase.js
define([], function() {
// exactly the same as `Father.js` from above
});
// Child.js
define(['FatherBase'], function(Father){
// exactly the same as `Child.js` from above
});
// Father.js
define(['FatherBase', 'Child'], function(Father, Child) {
// exactly the same as `FatherAugmentor.js` from above
});
将获得完整的课程,但您必须小心使用作为周期部分的文件中的Father
(即FatherBase
和Child.js
)。
可以考虑涉及命名空间对象的解决方案(即返回包含构造函数Father.js
和family
的{{1}}对象),但我认为它太难看了。
答案 1 :(得分:-1)
我知道这不是很好,并且正确地打破了一些优化和一些约定(比如处理具有相同名称的模块)。所以这是一个解决方案,它复制了全球范围内的所有模块。
<强> Child.js 强>
define(['Father'], function(){
// var Father = require("Father");
function Child(){
this.father = [];
}
Child.prototype.setFather = function(f){
if(!(f instanceof Father)){
alert("false");
}
}
window.Child = Child;
});
<强> Father.js 强>
define(['Child'], function () {
function Father() {};
Father.prototype.childs = [];
Father.prototype.addChild = function (c) {
if (!(c instanceof Child)) {
alert("nope");
}
};
window.Father = Father;
});
<强> app.js 强>
requirejs(['Child', 'Father'], function(){
var c = new Child();
var f = new Father();
c.setFather(f);
f.addChild(c);
console.log("done");
});
要同步加载(在更复杂的项目上),我使用一个中介来跟踪所需的加载,并在加载所有内容时触发事件。
而不是窗口,您可以使用https://stackoverflow.com/a/5573049/228763在其他平台上使用。