ESModule
es6模块化规范
采用的是
import 导入
export 导出
特点:
1:一个文件为一个模块,每一个模块只会加载一次,即使多次调用,还是加载一次,多次引入的时候,是从内存中获取
2:导出和导入
import导入 import
export导出 export defalut {}
3:import为静态的导入
导出
let a = 10
let b = 20
function add(a, b) {
return a + b
}
let c = 30
function sub(a, b) {
return a - b
}
export {
a,
b,
c,
add
}
let d = 100
let e = 22
export default {
d,
e
}//注意点:就是export default 导出的只能是一个变量或者对象等等!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
导入
import XXX form “路径” =>这是对应 export let XXX 的格式
import { } form “路径” =>这是对应 export {} 的格式
import XX from “路径” =>这是对应 export default {} 的格式
注意点:就是export 导入的必须按照导出的名称来接受,如果重名了,那么使用 as 来修改别名
eg: import { d as dd} from "路径" 当d变量重名的时候,就把个导出为dd
import {
a,
b,
c,
add
} from "./js/01.es6的导入和导出.js"
1
2
3
4
5
6
AMD
sea.js
CMD
require.js
commom.js
node语言的模块化规范
导出
var flag = true
function getSum(num, num2) {
return num + num2
}
if (flag) {
console.log('小明')
}
//这是common.js方式 导出 对象
module.exports = {
flag,
getSum
}
1
2
3
4
5
6
7
8
9
10
11
12
导入
语法:let {flag,getSum} = require 路径"
//这是commom.js导入的语法
let aaa = require('./aaa') // 从 aaa文件导入
let flag = aaa.flag
let getSum = aaa.getSum
// getSum(2, 90)
console.log(getSum(2, 90))
前端模块化在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可;如今CPU、浏览器性能得到了极大的提升,很多页面逻辑迁移到了客户端(表单验证等),随着web2.0时代的到来,Ajax技术得到广泛应用,jQuery等前端库层出不穷,前端代码日益膨胀
这时候JavaScript作为嵌入式的脚本语言的定位动摇了,JavaScript却没有为组织代码提供任何明显帮助,甚至没有类的概念,更不用说模块(module)了,JavaScript极其简单的代码组织规范不足以驾驭如此庞大规模的代码
模块
既然JavaScript不能handle如此大规模的代码,我们可以借鉴一下其它语言是怎么处理大规模程序设计的,在Java中有一个重要带概念——package,逻辑上相关的代码组织到同一个包内,包内是一个相对独立的王国,不用担心命名冲突什么的,那么外部如果使用呢?直接import对应的package即可
import java.util.ArrayList
遗憾的是JavaScript在设计时定位原因,没有提供类似的功能,开发者需要模拟出类似的功能,来隔离、组织复杂的JavaScript代码,我们称为模块化。
一个模块就是实现特定功能的文件,有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。模块开发需要遵循一定的规范,各行其是就都乱套了
规范形成的过程是痛苦的,前端的先驱在刀耕火种、茹毛饮血的阶段开始,发展到现在初具规模,简单了解一下这段不凡的历程
函数封装
我们在讲函数的时候提到,函数一个功能就是实现特定逻辑的一组语句打包,而且JavaScript的作用域就是基于函数的,所以把函数作为模块化的第一步是很自然的事情,在一个文件里面编写几个相关函数就是最开始的模块了
function fn1(){
statement
}
function fn2(){
statement
}
这样在需要的以后夹在函数所在文件,调用函数就可以了
这种做法的缺点很明显:污染了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间没什么关系。
对象
为了解决上面问题,对象的写法应运而生,可以把所有的模块成员封装在一个对象中
var myModule = {
var1: 1,
var2: 2,
fn1: function(){
},
fn2: function(){
}
}
这样我们在希望调用模块的时候引用对应文件,然后
myModule.fn2()
这样避免了变量污染,只要保证模块名唯一即可,同时同一模块内的成员也有了关系
看似不错的解决方案,但是也有缺陷,外部可以随意修改内部成员
myModel.var1 = 100
这样就会产生意外的安全问题
立即执行函数
可以通过立即执行函数,来达到隐藏细节的目的
var myModule = (function(){
var var1 = 1
var var2 = 2
function fn1(){
}
function fn2(){
}
return {
fn1: fn1,
fn2: fn2
}
})()
这样在模块外部无法修改我们没有暴露出来的变量、函数
上述做法就是我们模块化的基础,目前,通行的JavaScript模块规范主要有两种:CommonJS和AMD
CommonJS
我们先从CommonJS谈起,因为在网页端没有模块化编程只是页面JavaScript逻辑复杂,但也可以工作下去,在服务器端却一定要有模块,所以虽然JavaScript在web端发展这么多年,第一个流行的模块化规范却由服务器端的JavaScript应用带来,CommonJS规范是由NodeJS发扬光大,这标志着JavaScript模块化编程正式登上舞台。
定义模块
根据CommonJS规范,一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在该模块内部定义的变量,无法被其他模块读取,除非定义为global对象的属性
模块输出:
模块只有一个出口,module.exports对象,我们需要把模块希望输出的内容放入该对象
加载模块:
加载模块使用require方法,该方法读取一个文件并执行,返回文件内部的module.exports对象
现在常用的一种javascript的方法是在当前的html文档中插入一个script标签,在标签中引入script脚本Js代码var__includes__=newArrayArray.prototype.indexOf=function(obj){for(vari=0i<this.lengthi++){if(this[i]==obj)returni}return-1}Array.prototype.add=function(obj){this[this.length]=obj}functioninclude_js(js){if(__includes__.indexOf(js)-1)return__includes__.add(js)varhead=document.getElementsByTagName('head')[0]script=document.createElement('script')script.src=jsscript.type='text/javascript'head.appendChild(script)}当你只是在你的htmlw文档中使用这个方法的时候,一切OK,这其实是script的标签的一种快捷的写法而已。但是,如果你在一个javascript使用这个方法,问题就来了,比如我在test.js中使用include_js("test1.js"),在test1.js中有一个变量test1是在test.js中要使用的,在webkit中尽然出现了test1变量未定义的错误,我不知道ie和firefox是否有这种问题,我想可能是include_js本身不是同步执行导致的,所以我只好使用以下方法来完善inlcude_jsJs代码var__includes__=newArrayArray.prototype.indexOf=function(obj){for(vari=0i<this.lengthi++){if(this[i]==obj)returni}return-1}Array.prototype.add=function(obj){this[this.length]=obj}functionxhttp(url,callback){varrequest=nullif(typeofXMLHttpRequest!='undefined'){request=newXMLHttpRequest()}elseif(typeofActiveXObject!='undefined'){request=newActiveXObject('Microsoft.XMLHTTP')}request.open('GET',url,true)request.onreadystatechange=function(){if(request.readyState==4){callback(request.responseText)}}request.send(null)}functionadd_scripts(jss,callback){varfunc=function(jss,idx,callback){if(idx==jss.length){callback()return}add_script(jss[idx],function(){func(jss,++idx,callback)})}func(jss,0,callback)}functionadd_script(js,callback){if(__includes__.indexOf(js)-1){callback()return}__includes__.add(js)xhttp(js,function(js_content){varhead=document.getElementsByTagName('head')[0]script=document.createElement('script')head.appendChild(script)// script.innerHTML=js_content//原帖是这个...本人测试这行..无效 必须用text属性赋值script.defer=truescript.type='text/javascript'script.language='javascript'//本人测试修正..添加script.text=js_content//本人测试修正..添加//zfrong 09.5.20callback()})}functioninclude_js(js){if(__includes__.indexOf(js)-1)return__includes__.add(js)varhead=document.getElementsByTagName('head')[0]script=document.createElement('script')script.src=jsscript.type='text/javascript'head.appendChild(script)}当我在html文档中引入的时候,我用 include_js,当我在js文件中引入js时候,我使用add_scripts,add_scriptJs代码add_scripts(['test1.js','test2.js']),add_scripts方法使用了xmlhttp来读入js内容,并把读入的内容的写到一个新的script标签内,读入是异步执行的,当执行完毕后,会调用callback、