用纯Javascript打造类似NodeJS的模块载入系统

简介:
用纯Javascript打造类似NodeJS的模块载入系统2011-11-15 18:35:46      我来说两句       收藏     我要投稿

 http://www.2cto.com/kf/201111/111190.html

 

NodeJS的模块系统有两个重要的特点:

 

1. 模块中直接用var定义的变量是仅作用与当前模块的,而不是全局。

 

2. 每个模块中都可以使用require和module这两个“全局变量”。之所以打上引号,因为它们其实是每个模块都有的通用实例,不同模块中的实例是不一样的。

 

也许你会认为这两个特性和我们在浏览器中使用的Javascript性质有很多不同,一定是NodeJS运行环境提供的native特性,那就不一定了。尽管没有研究过NodeJS是如何实现的,但是我们用纯JavaScript完全可以做出一样的模块系统。这其实只要要用到一个Javascript中很少用的语法:new Function()。

 

 

 

Javascript中除了用function func(){}来定义一个函数之外,还可以用new Function()来创建一个函数。Function是Javascript中所有函数的prototype,即所有函数的基类。通过给Function.prototype增加属性可以给所有的函数实例增加属性,这也是大家相对常用的一个做法。今天要给大家介绍的是通过直接new Function()来创建一个函数,尽管这被认为性能不好,但在某些特殊场景能做到一些很有用的功能。

 

 

new Function()的详细语法格式是:

 

 

new Function(args, body) 

这里的args是一个字符串,表示函数的参数,参数之间用逗号隔开,而body则是函数体本身。比如:

var add = new Function('x, y', 'return x + y;');

这样创建的函数就等价于:

 

var add = function(x, y){ 

     return x + y; 

这两者效果没有任何区别,通常我们也只会用第二种做法,因为有更好的可读性。

 

 

现在我们来看new Function的两种潜在应用场景:

1. 避免命名冲突

大家知道通过<script>标签引入的Javascript文件是全局的,每个文件中定义的变量都是全局的,这时为了避免命名冲突,可以通过如下的小技巧:

 

(function(){ 

     var x = 0; 

     //my code 

})(); 

通过外包一个函数并立刻调用,可以做成一个闭包,其中的变量的作用域就只局限于函数体之内。从而避免了与其它的文件之间的命名冲突。但是在有些情况下,我们需要使用一个第三方的Javascript文件或者因为某些原因而无法修改的文件,它完成某个独立的任务,但是其中定义了一些全局变量。这些文件无法被修改成使用上面提到的方法来避免命名冲突。这时我们的new Function()就可以发挥作用了。这时我们不是通过<script>引入Javascript文件,而是通过XMLHttpRequest获得Javascript文件的内容,然后用如下的方式来执行这个Javascript:

 

var result = (new Function('', jsCode + '; return {x: x}'))(); 

这样,我们相当于也是在jsCode外面包装了一层function,并且,我们把需要用的的结果作为返回值返回出来,供外面程序使用。当然,对于大部分独立的文件,我们并不一定需要返回值,而只是需要执行一下即可。下面来看下一个应用场景。

 

 

2. 打造自己的模块载入系统

这也是上一种应用场景的一个延伸,既然我们通过这种方式来载入Javascript文件,何不将其做成一个通用的模块载入系统,供自己的项目使用。从而不用每个文件都外包一层function来避免命名冲突。其实如果大家用过NodeJS,就也许知道,NodeJS中的每个模块中定义的变量都是局限于当前模块的,不会被其它模块直接使用。而且每个模块中还有一个默认的require和module变量,这两个每个模块中都可以像使用全局变量一样使用,但它们却又不是全局变量,NodeJS文档中写的也很清楚,它们在各个模块中都是不同的实例。这样,一个模块都它们进行的修改并不会影响到其它模块。你也许会认为这一定是NodeJS的native环境提供的特殊功能,但实际上,我们完全可以用纯Javascript打造出一个同样的模块机制,只需对上面提到的例子做一点修改,比如这个loader是有类似如下的代码:

 

var require = getRequireInstance(); 

var module = getModuleInstance(); 

 //通过XMLHttpRequest获得要载入的Javascript文件的代码 

var moduleText = getModuleText();   

//执行模块代码,并“注入”require和module变量。 

(new Function('require, module', moduleText))(require, module); 

怎么样,是不是很简单?new Function()虽然是一个很少用的功能,但是确实非常灵活,更多应用场景就靠大家继续挖掘了

 

摘自 Dojo中文博客-

相关文章
|
14天前
|
JavaScript 前端开发 容器
AJAX载入外部JS文件到页面并让其执行的方法(附源码)
AJAX载入外部JS文件到页面并让其执行的方法(附源码)
16 0
|
2月前
|
JavaScript
Node.js【GET/POST请求、http模块、路由、创建客户端、作为中间层、文件系统模块】(二)-全面详解(学习总结---从入门到深化)
Node.js【GET/POST请求、http模块、路由、创建客户端、作为中间层、文件系统模块】(二)-全面详解(学习总结---从入门到深化)
27 0
|
8天前
|
开发框架 前端开发 JavaScript
采用C#.Net +JavaScript 开发的云LIS系统源码 二级医院应用案例有演示
技术架构:Asp.NET CORE 3.1 MVC + SQLserver + Redis等 开发语言:C# 6.0、JavaScript 前端框架:JQuery、EasyUI、Bootstrap 后端框架:MVC、SQLSugar等 数 据 库:SQLserver 2012
|
11天前
|
域名解析 网络协议 JavaScript
【Node系列】node工具模块
Node.js有多个内置的工具模块,这些模块提供了用于执行各种任务的功能。
21 2
|
26天前
11_nest.js模块
11_nest.js模块
23 0
|
1月前
|
JavaScript 前端开发
Node.js之path路径模块
Node.js之path路径模块
|
1月前
|
JavaScript
Node.js之http模块
Node.js之http模块
|
2月前
|
JavaScript 前端开发 关系型数据库
分享66个NodeJs系统源码总有一个是你想要的
分享66个NodeJs系统源码总有一个是你想要的
34 1
|
2月前
|
JavaScript
什么是Vue.js的响应式系统(reactivity system)?如何实现数据的双向绑定?
什么是Vue.js的响应式系统(reactivity system)?如何实现数据的双向绑定?
19 0
|
2月前
|
资源调度 JavaScript 关系型数据库
Node.js【文件系统模块、路径模块 、连接 MySQL、nodemon、操作 MySQL】(三)-全面详解(学习总结---从入门到深化)
Node.js【文件系统模块、路径模块 、连接 MySQL、nodemon、操作 MySQL】(三)-全面详解(学习总结---从入门到深化)
33 0