我习惯使用Java编程,我们知道每个对象通常定义在自己的文件中。我喜欢这样做,因为它让代码更易于管理和操作。
现在我开始使用JavaScript编程,并发现自己希望在单个页面上使用不同的脚本时采用单独的文件进行编写。目前,我只使用了几个 .js 文件,因为我担心如果我使用更多,未来可能会遇到一些难以预料的问题,例如循环引用。
简而言之,将我的脚本分成多个文件是一个不好的实践吗?
我习惯使用Java编程,我们知道每个对象通常定义在自己的文件中。我喜欢这样做,因为它让代码更易于管理和操作。
现在我开始使用JavaScript编程,并发现自己希望在单个页面上使用不同的脚本时采用单独的文件进行编写。目前,我只使用了几个 .js 文件,因为我担心如果我使用更多,未来可能会遇到一些难以预料的问题,例如循环引用。
简而言之,将我的脚本分成多个文件是一个不好的实践吗?
这取决于您的应用程序大小以及您要将其交付给谁(我指的是预期设备等),以及您在服务器端可以执行多少工作来确保针对正确的设备(对于大多数非企业人员而言,这仍然远未达到100%可行)。
构建应用程序时,“类”可以快乐地存在于它们自己的文件中。
当将应用程序分割成文件或处理假定太多的构造函数的类(例如实例化其他类)时,循环引用或死结引用 ARE 是一个重大问题。
有多种模式可解决此问题,但最好的方法当然是考虑 DI /IoC 来构建您的应用程序,以便避免循环引用。
您还可以查看 require.js 或其他依赖项加载器。 您需要变得多么复杂取决于应用程序的大小以及您希望所有内容保持多私密。
在为应用程序提供服务时,提供 JS 的基线是将您需要的所有脚本连接在一起(如果您要实例化假定其他东西存在的东西,则按正确顺序),并将它们作为页面底部的一个文件提供。
但那是基线。
其他方法可能包括“懒/延迟”加载。
加载所有需要使页面工作的东西。
同时,如果您有不需要在页面加载时完全使用其功能的小应用程序或小部件,并且实际上,它们需要用户交互或需要一定时间延迟才能执行任何操作,则将这些小部件的脚本加载设置为延迟事件。 当用户按下选项卡时加载选项卡小部件的脚本。 现在您只加载了所需的脚本,并且仅在需要时加载,没有人会真正注意到下载时的微小延迟。
与试图将 40,000 行应用程序塞入一个文件的人进行比较。
仅有一个 HTTP 请求和一个下载,但解析/编译时间现在成为可察觉的秒数分数。
class MyClass extends MyParent { }
这样的类。我对此的感受放在一边,我在示例中使用类是为了语义上让人们理解“模块化可重用性的不同部分”的概念。JS给你做任何事情的无数种方式。如果你把所有东西都包装在IIFEs中,保存在单独的文件中,那么如何在运行时将它们连接起来?什么是唯一的标准方法?没有。熟悉C++/Java/PHP/Python/Ruby等语言的人都能理解。 - Norguardfunction MyClass(a) { this.member = a; this.method = function () {}; } var myClass = new MyClass();
是JS提供的最接近类的东西,因此是他们应用结构的基础,如果他们没有其他JS经验。人们似乎在this
和new
中找到了安慰。此外,答案是针对一个问题量身定制的,如果您重新阅读一下... - Norguard2020年更新:从互联网标准来看,本答案已经非常陈旧,与当今情况相去甚远,但是它仍然偶尔获得投票,因此我觉得有必要提供一些关于自发布以来发生变化的提示。支持async
脚本加载、HTTP/2服务器推送功能以及多年来对加载过程的通用浏览器优化,都对将Javascript分解为多个文件对加载性能的影响产生了影响。
对于那些刚开始学习Javascript的人,我的建议仍然不变(使用打包工具/缩小工具,并信任其默认情况下会做正确的事情),但对于任何发现这个问题的人,他们都有更多的经验,我邀请他们探索async
加载和服务器推送带来的新功能。
2013年左右的原始回答:
由于下载时间,您应该尝试使您的脚本成为一个单独的大文件。然而,如果您使用缩小工具(您应该使用缩小工具),它们可以为您将多个源文件合并为一个文件。因此,您可以继续在多个文件上工作,然后将它们缩小为一个文件进行分发。
主要例外是公共库,如jQuery,您应该始终从公共CDN加载它们(更有可能用户已经加载它们,因此不需要再次加载)。如果您确实使用了公共CDN,则一定要有一个回退以从自己的服务器加载。
如评论中所述,真相略有复杂;
脚本可以同步加载(<script src="blah"></script>
)或异步加载(s=document.createElement('script');s.async=true;...
)。同步脚本阻止加载其他资源直到它们加载完成。例如:
<script src="a.js"></script>
<script src="b.js"></script>
会请求 a.js 并等待其加载,然后再加载 b.js。在这种情况下,将 a.js 与 b.js 结合并一次性加载它们显然更好。
同样地,如果 a.js 中有用于加载 b.js 的代码,无论它们是异步还是同步,您都将面临相同的情况。
但是,如果您同时异步加载它们,并根据客户端与服务器之间连接的状态以及许多只能通过分析来确定的考虑因素,这可能会更快。
(function(d){
var s=d.getElementsByTagName('script')[0],f=d.createElement('script');
f.type='text/javascript';
f.async=true;
f.src='a.js';
s.parentNode.insertBefore(f,s);
f=d.createElement('script');
f.type='text/javascript';
f.async=true;
f.src='b.js';
s.parentNode.insertBefore(f,s);
})(document)
虽然更为复杂,但是可以同时加载 a.js 和 b.js,而不会相互阻塞或影响其他内容。最终,async
属性将会得到更好的支持,届时你就可以像同步加载一样轻松地完成此操作了。不过这需要时间。
这并不重要。如果您在多个文件中使用相同的JavaScript,那么拥有一个从中获取JavaScript的文件肯定是很好的。这样,您只需要从一个地方更新脚本即可。