我正在尝试编写一个足够大的javaScript应用程序,模块化可能是一个好主意。我使用着名的继承函数来使对象从具有参数的构造函数继承。问题是我得到一个错误,传递给继承函数的父是未定义的。这是因为,当调用inherit时,尚未定义父构造函数。
我想出了一些解决这个问题的丑陋方法:
在父母(yuk)之后声明所有子构造函数。
将所有原型分配绑定到自定义事件,并使用有序的回调链来确保按顺序分配所有原型(可能存在潜在的原型)。
从构造函数所在的代码区域中移动所有原型赋值,并将它们合并(并放逐)到某些“assign prototypes”函数(第一项yuk的两倍,不是吗?)。
底线是我不希望基于我的构造函数,方法和对象在代码中按照加载/解释代码的顺序编写的顺序。我希望我的代码易于扩展,并且相关代码组合在一起,因此很容易理解(即,原型赋值是否应该靠近构造函数声明/定义?)。
我将模块放在单独的文件中,并在将它们发送到浏览器之前使用PHP脚本将它们全部附加在一起。 PHP脚本只确保首先包含声明命名空间的文件,之后它将js文件与glob连接。
我写了一个小脚本,完全展示了我遇到的问题。它是is live at this url。屏幕是白色的,因为没有html - 我在这里使用控制台进行分析。
/*global console, jQuery, $, myNS: true*/
/*jslint browser: true*/
/*
* This file is deliberately set as the first file in the php glob.
*/
var myNS = (function (myNS, $, window, undefined) {
"use strict";
/*
* @param {object} coords -- e.g. {x: 3, y: 26}
*/
myNS = function (coords) {
return new myNS.CartesianLoc(coords);
};
// static methods
myNS.inherit = function (parent) {
function F() {}
F.prototype = parent.prototype;
return new F();
};
myNS.getWinCenter = function () {
return {
x : $(window).width() / 2,
y : $(window).height() / 2
};
};
// prototype
myNS.prototype = {
log: function () {
if (window.console) {
console.log(this);
}
}
};
return myNS;
}(myNS, jQuery, window));
/*
* This is another file.
*/
(function (myNS, $, window, undefined) {
"use strict";
/*
* CartesianLoc constructor
*
* @param {object} coords -- given in a conceptual
* Cartesian space where the origin (0,0) is
* the middle of whatever screen
*/
function CartesianLoc(coords) {
myNS.Loc.call(this, coords);
}
CartesianLoc.prototype = myNS.inherit(myNS.Loc);
CartesianLoc.prototype.constructor = CartesianLoc;
CartesianLoc.prototype.getWinCoords = function () {
return {
x: myNS.getWinCenter().x + this.x,
y: myNS.getWinCenter().y + this.y
};
};
myNS.CartesianLoc = CartesianLoc;
}(myNS, jQuery, window));
/*
* This is another file.
*/
(function (myNS, $, window, undefined) {
"use strict";
// Location constructor
function Loc(coords) {
this.x = coords.x;
this.y = coords.y;
}
Loc.prototype = myNS.inherit(myNS);
Loc.prototype.constructor = Loc;
Loc.prototype.translate = function (coords) {
this.loc.x += coords.x;
this.loc.y += coords.y;
return this;
};
myNS.Loc = Loc;
}(myNS, jQuery, window));
/*
* Application js file
*
*/
(function (myNS, $, window, undefined) {
"use strict";
$(document).ready(function (event) {
if (console) {
console.log("%o", new myNS({x: 100, y: -45}));
}
});
}(myNS, jQuery, window));
感谢你给我的任何帮助或想法!
克里斯
答案 0 :(得分:0)
我不确定这是一个合理的练习还是凌乱,但我创建了一个在document.ready上触发的自定义事件,并将所有在回调中分配原型的代码放置到该事件中。我知道我正在添加一个事件,当另一个事件被触发时触发它(这看起来毫无意义),但我希望自定义事件是一个被监听的事件,以防我想要改变以后触发它的方式。
/*global console, jQuery, $, myNS: true*/
/*jslint browser: true*/
/*
* This file is deliberately set as the first file in the php glob.
*/
var myNS = (function (myNS, $, window, undefined) {
"use strict";
/*
* @param {object} coords -- e.g. {x: 3, y: 26}
*/
myNS = function (coords) {
return new myNS.CartesianLoc(coords);
};
// Triggered after all constructors have been defined
$(document).ready(function (event) {
$(document).trigger("myNS");
});
// static methods
myNS.inherit = function (parent) {
function F() {}
F.prototype = parent.prototype;
return new F();
};
myNS.getWinCenter = function () {
return {
x : $(window).width() / 2,
y : $(window).height() / 2
};
};
// prototype
myNS.prototype = {
log: function () {
if (window.console) {
console.log(this);
}
}
};
return myNS;
}(myNS, jQuery, window));
/*
* This is another file.
*/
(function (myNS, $, window, undefined) {
"use strict";
/*
* CartesianLoc constructor
*
* @param {object} coords -- given in a conceptual
* Cartesian space where the origin (0,0) is
* the middle of whatever screen
*/
function CartesianLoc(coords) {
myNS.Loc.call(this, coords);
}
$(document).on('myNS', function (event) {
CartesianLoc.prototype = myNS.inherit(myNS.Loc);
CartesianLoc.prototype.constructor = CartesianLoc;
CartesianLoc.prototype.getWinCoords = function () {
return {
x: myNS.getWinCenter().x + this.x,
y: myNS.getWinCenter().y + this.y
};
};
});
myNS.CartesianLoc = CartesianLoc;
}(myNS, jQuery, window));
/*
* This is another file.
*/
(function (myNS, $, window, undefined) {
"use strict";
// Location constructor
function Loc(coords) {
this.x = coords.x;
this.y = coords.y;
}
$(document).on('myNS', function (event) {
Loc.prototype = myNS.inherit(myNS);
Loc.prototype.constructor = Loc;
Loc.prototype.translate = function (coords) {
this.loc.x += coords.x;
this.loc.y += coords.y;
return this;
};
});
myNS.Loc = Loc;
}(myNS, jQuery, window));
/*
* Application js file
*
*/
(function (myNS, $, window, undefined) {
"use strict";
$(document).ready(function (event) {
if (console) {
console.log("%o", new myNS({x: 100, y: -45}));
}
});
}(myNS, jQuery, window));