如何将一个js文件包含到另一个js文件中,以坚持DRY原则,避免代码重复。


当前回答

我不同意这份文件。写作技巧(见Vahan Margaryan的建议)。我喜欢document.getElementsByTagName('head')[0]. appendchild(…)(参见Matt Ball的建议),但有一个重要的问题:脚本执行顺序。

Recently, I have spent a lot of time reproducing one similar issue, and even the well-known jQuery plugin uses the same technique (see src here) to load the files, but others have also reported the issue. Imagine you have JavaScript library which consists of many scripts, and one loader.js loads all the parts. Some parts are dependent on one another. Imagine you include another main.js script per <script> which uses the objects from loader.js immediately after the loader.js. The issue was that sometimes main.js is executed before all the scripts are loaded by loader.js. The usage of $(document).ready(function () {/*code here*/}); inside of main.js script does not help. The usage of cascading onload event handler in the loader.js will make the script loading sequential instead of parallel, and will make it difficult to use main.js script, which should just be an include somewhere after loader.js.

通过在我的环境中重现这个问题,我可以看到,在Internet Explorer 8中,脚本的执行顺序会因包含JavaScript而有所不同。如果您需要包含相互依赖的脚本,这将是一个非常困难的问题。这个问题在并行加载Javascript文件中有描述,建议的解决方法是使用document.writeln:

document.writeln("<script type='text/javascript' src='Script1.js'></script>");
document.writeln("<script type='text/javascript' src='Script2.js'></script>");

因此,在“脚本是并行下载的,但按照它们写入页面的顺序执行”的情况下,将document. getelementsbytagname ('head')[0]. appendchild(…)技术更改为document. getementsbytagname ('head')。写完之后,我再也没有看到过这个问题。

所以我建议你使用document。writeln。

UPDATED:如果有人感兴趣,他们可以尝试在Internet Explorer中加载(并重新加载)页面(页面使用document.getElementsByTagName('head')[0]. appendchild(…)技术),然后与使用document.writeln的固定版本进行比较。(该页的代码是相对肮脏的,不是来自我,但它可以用来重现问题)。

其他回答

这是不可能直接的。你也可以写一些预处理程序来处理它。

如果我的理解正确,那么以下是可以帮助实现这一目标的事情:

Use a pre-processor which will run through your JS files for example looking for patterns like "@import somefile.js" and replace them with the content of the actual file. Nicholas Zakas(Yahoo) wrote one such library in Java which you can use (http://www.nczonline.net/blog/2009/09/22/introducing-combiner-a-javascriptcss-concatenation-tool/) If you are using Ruby on Rails then you can give Jammit asset packaging a try, it uses assets.yml configuration file where you can define your packages which can contain multiple files and then refer them in your actual webpage by the package name. Try using a module loader like RequireJS or a script loader like LabJs with the ability to control the loading sequence as well as taking advantage of parallel downloading.

JavaScript目前还没有提供像CSS (@import)这样的“原生”方式来将JavaScript文件包含到另一个文件中,但上面提到的所有工具/方法都有助于实现你提到的DRY原则。我可以理解,如果你来自服务器端背景,这可能感觉不直观,但事情就是这样。对于前端开发人员来说,这个问题通常是“部署和打包问题”。

希望能有所帮助。

你需要写一份文件。写对象:

document.write('<script type="text/javascript" src="file.js" ></script>');

并将其放在主javascript文件中

只能在HTML页面中包含脚本文件,而不能在另一个脚本文件中包含脚本文件。也就是说,你可以编写JavaScript加载你的“包含”脚本到同一页面:

var imported = document.createElement('script');
imported.src = '/path/to/imported/script';
document.head.appendChild(imported);

您的代码很有可能依赖于“包含的”脚本,但是,在这种情况下,它可能会失败,因为浏览器将异步加载“导入的”脚本。最好的办法是使用jQuery或YUI这样的第三方库,它们可以为您解决这个问题。

// jQuery
$.getScript('/path/to/imported/script.js', function()
{
    // script is now loaded and executed.
    // put your dependent JS here.
});

我不同意这份文件。写作技巧(见Vahan Margaryan的建议)。我喜欢document.getElementsByTagName('head')[0]. appendchild(…)(参见Matt Ball的建议),但有一个重要的问题:脚本执行顺序。

Recently, I have spent a lot of time reproducing one similar issue, and even the well-known jQuery plugin uses the same technique (see src here) to load the files, but others have also reported the issue. Imagine you have JavaScript library which consists of many scripts, and one loader.js loads all the parts. Some parts are dependent on one another. Imagine you include another main.js script per <script> which uses the objects from loader.js immediately after the loader.js. The issue was that sometimes main.js is executed before all the scripts are loaded by loader.js. The usage of $(document).ready(function () {/*code here*/}); inside of main.js script does not help. The usage of cascading onload event handler in the loader.js will make the script loading sequential instead of parallel, and will make it difficult to use main.js script, which should just be an include somewhere after loader.js.

通过在我的环境中重现这个问题,我可以看到,在Internet Explorer 8中,脚本的执行顺序会因包含JavaScript而有所不同。如果您需要包含相互依赖的脚本,这将是一个非常困难的问题。这个问题在并行加载Javascript文件中有描述,建议的解决方法是使用document.writeln:

document.writeln("<script type='text/javascript' src='Script1.js'></script>");
document.writeln("<script type='text/javascript' src='Script2.js'></script>");

因此,在“脚本是并行下载的,但按照它们写入页面的顺序执行”的情况下,将document. getelementsbytagname ('head')[0]. appendchild(…)技术更改为document. getementsbytagname ('head')。写完之后,我再也没有看到过这个问题。

所以我建议你使用document。writeln。

UPDATED:如果有人感兴趣,他们可以尝试在Internet Explorer中加载(并重新加载)页面(页面使用document.getElementsByTagName('head')[0]. appendchild(…)技术),然后与使用document.writeln的固定版本进行比较。(该页的代码是相对肮脏的,不是来自我,但它可以用来重现问题)。