如何将我的JavaScript代码拆分为不同的文件?

28
我正在阅读来自Mozilla的JavaScript Guide,当他们将JS与Java进行对比时,这让我想到,Java代码可以轻松地分割到每个类自己的文件中。经过进一步搜索,我了解到可以使用命名空间和模块模式在JS中实现相同的功能。我尝试了一下,但非常困惑(特别是在将在File1.js中声明的构造函数调用到File2.js中时)。所以这是层次结构:class organization但我就是无法弄清楚如何使其正常工作。从哪里开始?
//employe.js
function Employee () {
  this.name = "";
  this.dept = "general";
}

function Manager () {
  this.reports = [];
}
Manager.prototype = new Employee;

function WorkerBee () {
  this.projects = [];
}
WorkerBee.prototype = new Employee;

function SalesPerson () {
  this.dept = "sales";
  this.quota = 100;
}
SalesPerson.prototype = new WorkerBee;

变成这样:

 // employe.js
function Employee () {
  this.name = "";
  this.dept = "general";
}

 // Manager.js   
function Manager () {
  this.reports = [];
}
Manager.prototype = new Employee;

 // WorkerBee.js     
function WorkerBee () {
  this.projects = [];
}
WorkerBee.prototype = new Employee;

 // SalesPerson.js      
function SalesPerson () {
 this.dept = "sales";
 this.quota = 100; 
 }
SalesPerson.prototype = new WorkerBee;

2
你所要做的就是按正确顺序包含文件。 - Felix Kling
@FelixKling:由于代码仅声明构造函数而不创建任何内容,因此包含文件的顺序甚至并不重要。 - Guffa
@Guffa:是的,它们正在创建一个原型继承的实例,例如 Manager.prototype = new Employee; - Felix Kling
@FelixKling:哦,你是对的。我承认错误了。它们确实需要按正确顺序包含进来。 - Guffa
如果使用现代的class,我会像这样解决这个问题:https://dev59.com/9VkS5IYBdhLWcg3wSktG#62142995 - Andrew
3个回答

20

你应该拥有一个全局的命名空间对象,每个模块都需要访问和写入。请按以下方式修改您的文件:

你应该拥有一个全局的命名空间对象,每个模块都需要访问和写入。请按以下方式修改您的文件:

// employe.js

window.myNameSpace = window.myNameSpace || { };

myNameSpace.Employee = function() {
    this.name = "";
    this.dept = "general";
};

并且Manager.js看起来可能像这样

// Manager.js

window.myNameSpace = window.myNameSpace || { };

myNameSpace.Manager = function() {
    this.reports = [];
}
myNameSpace.Manager.prototype = new myNameSpace.Employee;

当然,这只是一个非常简化的例子。因为加载文件和依赖项的顺序不是易如反掌的。有一些好的库和模式可用,我建议您看看requireJSAMDCommonJS模块模式。 http://requirejs.org/


这很有道理,谢谢 - 我看了requireJS,但我不太明白它怎样能帮助我 - 我想我把require php style和JS搞混了。 - MimiEAM
1
我猜你在每个文件中添加了 window.myNameSpace = window.myNameSpace || { }; 以避免任何加载错误。这正确吗? - zachdyer
@zachdyer 我同意。只需查看EaseIJS的操作方式:https://github.com/CreateJS/EaselJS/blob/master/src/easeljs/filters/BlurFilter.js,它使用了相同的技巧。 - user5066707

8

您不需要有任何不同的操作。只需包含脚本文件,它们就会像单个文件一样工作。

Javascript没有文件作用域。一旦代码被解析,代码来自哪里就无关紧要了。


3
正确,但这并不是良好的实践,也不方便。你应该提到这只能工作是因为全局对象是自己的变量对象,因此所有varfunction声明都会隐式地写入它。像这样破坏全局对象仍然是不好的行为。 - jAndy
1
@jAndy:是的,你说得对,将标识符保持在全局范围之外是更好的实践方法,但这并不是将代码放入单独文件中所必需的步骤。 - Guffa
@Guffa,我一直在读到我们应该避免“污染”全局作用域,除了不暴露我们不想修改的变量之外,还有其他原因吗? - MimiEAM
3
@MimiEAM:是的。当您在页面中使用多个脚本库时,如果它们定义较少的全局标识符,则它们之间的标识符冲突风险会降低。 - Guffa
今天的JS类不是这样的。 - Andrew

5
对于像网站或游戏这样的小型和中型项目,本地命名空间和构造函数非常适用。但如果加载顺序过于复杂而无法处理,则它们是一个糟糕的选择,需要使用某种自动加载方式。
index.html:
<script src="Employee.js"></script>
<script src="Manager.js"></script>

Manager.js:

var Manager = function() {
    var employee1 = new window.Employee(this);
    var employee2 = new window.Employee(this);
};

Employee.js:

var Employee = function(boss) {
    // work stuff here
    this.wage = 5;
};

注意,员工构造函数内部的属性对经理可见。 new 关键字表示构造函数。也可以通过返回具有属性的对象而不是函数来实现无需构造函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接