功能实现之简单的模块化实现

一直在使用模块化,但是一直不知道如何利用JS自主实现,忽然一天我想到了其中的一个可行的方法,下面我就介绍一下。

模块化

因为HTML5 CSS3 的出现,web前端比过去要丰富强大的多。能开发越来越复杂的应用,但当应用越来越复杂的时候,如果还是用以前的方法来编程,前端工程维护成本会越来越高,最后集中到一个点就会一发不可收拾。

为此需要使用模块化来分解复杂的应用,使各个模块间最大限度的解耦,减少代码的重复开发,提高开发效率,降低维护成本。

模块化的JS实现

已有的实现

ES6 import/export

ES6(es2015)中新添加了import和export来实现模块化。

AMD(RequireJS)/CMD(SeaJS)

现在主流的模块化有两个规范AMDCMD,分别的代表为RequireJSSeaJS

模块化的简单实现

1.加载运行JS文件

模块化使各个模块JS存储在不同的文件当中,获取文件并加载运行JS文件是首要解决的问题。

在JS中使用文本实时进行允许的方法主要就两个:

eval()

eval函数是一个解析字符串为JS运行的函数。是最简单的允许JS代码的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//test.js
console.log('我来啦!');

//main.html
ajax({
reqURL:"./test.js",
reqHeader:{
"Accept":"text/plain"
},
reqSuccess:function(data){
eval(data);//输出我来了
}
});

但是eval函数有很多弊端

弊端之一:使用的全局环境
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//test.js
var x=123;

//main.html
ajax({
reqURL:"./test.js",
reqHeader:{
"Accept":"text/plain"
},
reqSuccess:function(data){
eval(data);
console.log(x);//123
}
});
弊端之二:使用的全局环境,同时无法被JS解析器进行解析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//test.js
var x=123;

//main.html
ajax({
reqURL:"./test.js",
reqHeader:{
"Accept":"text/plain"
},
reqSuccess:function(data){
console.log(x);//报错没有x变量,没有进行声明提前
eval(data);
}
});

new Function()

除了 eval 函数,使用new Function()是很好的一个实现模块化的方法。因为它构造了一个函数,提供了函数的作用域,同时使用严格模式,内部的实现就避免了对全局污染。并且可以设置传入对象和传出对像,利于模块化的实现。

模拟实现的一个简单的requier函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//test.js
var x=123;
exports.biu=function(){
console.log('biubiubiu');
}

//main.html
function require(path){
var exports={};
ajax({
reqURL:path,
reqAsync:false,//这里采用同步请求,方便处理(正是同异步处理不同,才有了AMD和CMD两大模块化规范)
reqSuccess:function(data){
new Function('exports',data)(exports);
}
});
return exports;
}

var test=require('./test.js');
console.log(x);//会报错没有X 说明 X的定义没有污染到全局
test.biu();//输出 biubiubiu

这只是简单的实现,模块化考虑和东西还很多,比如就现在的代码还能简单的优化一些

加入严格模式

当我们的代码是这样的时候

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//test.js
x=123;

//main.html
function require(path){
var exports={};
ajax({
reqURL:path,
reqAsync:false,//这里采用同步请求,方便处理(正是同异步处理不同,才有了AMD和CMD两大模块化规范)
reqSuccess:function(data){
new Function('exports',data)(exports);
}
});
return exports;
}

var test=require('./test.js');
console.log(x);//输出123

可见我们可能一时的疏忽没有写声明符就会导致变量变成全局的,导致对全局的污染。

这时我们就可以加入全局模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//test.js
x=123;

//main.html
function require(path){
var exports={};
ajax({
reqURL:path,
reqAsync:false,//这里采用同步请求,方便处理(正是同异步处理不同,才有了AMD和CMD两大模块化规范)
reqSuccess:function(data){
data='"use strict";'+data;
new Function('exports',data)(exports);//Uncaught ReferenceError: y is not defined
}
});
return exports;
}

var test=require('./test.js');

加入严格模式后我们就可以尽量避免对全局的污染,但写代码的时候还是得注意- -、

END

2016-12-19 完成

2016-12-12 立项