- 原始写法:
function m1(){
}
function m2(){
}
简单的将函数放在全局中,使用时直接调用
弊端:造成全局变量的污染,无法保证不与全局发生冲突 - 对象写法:
var obj = {
m1:function(){
};
m2:function(){
}
}
调用:obj.m1(); obj.m2();在使用时进行调用
弊端:将内部的模块暴露在外面,外部代码会将其改写 - 立即执行函数写法:
IIFE模式:
var $.getVal = (function($) {
var $p = $('input');
function getVal() {
return $p.val();
}
return {
getVal: getVal,
};
})(jQuery);
//放大模式:
var module = (function(mod) {
mod.add = function(a, b) {
return a + b;
};
return mod;
})(module);
调用:可以达到不暴露私有成员的目的
弊端:外部代码无法读取其中私有变量的值
module是javascript模块的基本写法
主流模块规范
目前通行的模块规范有两种:AMD和CommonJs
- Common.js规范
在CommonJS中,加载模块用require,即var math = require(“math”);然后就可以调用其方法math.add(a,b);
在CommonJS中,会暴露出module.exports和exports
module.exports对象是模块系统自己建立的,而exports在模块的文件级别才有作用
module.exports对象是由模块系统创建的。 有时这是难以接受的;许多人希望他们的模块成为某个类的实例。 为了实现这个,需要将期望导出的对象赋值给module.exports。 注意,将期望的对象赋值给exports会简单地重新绑定到本地exports变量上,这可能不是你想要的
exports变量是在模块的文件级别作用域内有效的,它在模块被执行前被赋于 module.exports 的值。它有一个快捷方式,以便 module.exports.f = … 可以被更简洁地写成exports.f = …。 注意,就像任何变量,如果一个新的值被赋值给exports,它就不再绑定到module.exports(其实是exports.属性会自动挂载到没有命名冲突的module.exports.属性)
//CommonJS:
function require(...){
var module = {
exports: {}
}
((module,exports) => {
function someFunc(){};
//每个js文件一创建,都有一个var exports = module.exports = {},使exports和module.exports都指向一个空对象,意味着两者地址相同
exports = someFunc;
//覆盖exports
module.exports = someFunc;
}(module,module.exports));
return module.exports;
}
- AMD规范
背景:有了服务器端模块,大家会想到有客户端模块,而且最好是两者兼容,一个模块不用修改,在两个地方都能执行。
而有一个很大的局限性,CommonJS不能很好的兼容客户端
var math = require("math");
math.add(a,b);
以上代码,在第一行运行require代码后,运行math.add()时,需要math.js加载完成之后,才会执行math.add()方法,也就意味着如果math.js加载很慢的话,整个程序会受到很大的影响,这就是commonJS的弊端。为了解决这种弊端,AMD采用异步加载的方式加载模块,客户端的加载快慢取决于网速的快慢,对于服务端就不一样,加载的快慢取决于读取磁盘的快慢,所以模块的加载不能用同步加载。
AMD模式下,模块必须通过define()方法进行定义,define(id,dependencies,factory)id:字符串,可选,dependencies:依赖模块,可选,factory:工厂方法,返回函数 引用模块:require()来引用模块,但与CommonJS不同的是,在这里的require()是两个参数,require([“module”],callback),引入的模块必须放到数组中,第二个参数是返回函数,例如:
require([“math”],function(math){
math.add(a,b);
})
math加载和math.add是不同步的,所以浏览器不会出现假死状态
目前AMD模式的JS库有:require.js和curl.js
- CMD规范
seaJS推崇的规范,依赖就近原则
定义模块
define(function(require,export,module){
//引用模块
var clock = require(‘clock’);
clock.start();
})
OR
define(id,“JQuery”,function(require,export,module){
//模块代码
})
引用模块
与AMD模式一致
AMD与CMD的区别:
AMD依赖前置,js方便知道模块是谁,直接加载
CMD就近依赖,需要把模块变成字符串解析一遍,才知道哪些依赖 - 现阶段规范
export导出模块
export语法声明导出函数、对象、指定文件(或模块)的原始值(node中使用exports)
export有两种导出模式:
a、命名式导出
export{myFunction} 导出已定义的函数
export const foo = “a”;导出一个常量
模块继承:export * from “module”
导出重命名:export {name as resetName}; =>关键字如default等不允许
b、默认导出
export default function(){}=>导出函数
export default class(){}=>导出一个类
import导入模板
a、命名式导入:
{}里的变量名与export一一对应
import {member} from “module”; 导入一个模块
import * from “module”=>导入全部的属性及其方法
as 别名:import {a as newName} from “module”;
导入一个模块但是不进行绑定:import “module”;
b、默认导入:
import myDefault from “module”;
指定成员导入:import myDefault ,{member1.member2} from “module”;
import和import使用实例:
/*file.js*/
function request(url,callback){
let xhr = new XMLHttpRequest();
xhr.onload = function(){
callback(this.responseText);
};
xhr.open("get",url,false);
xhr.send();
}
export function getUsefulContents(url, callback) {
request( url, data => callback(JSON.parse(data)));
}
/*main.js*/
import getUsefulContents from "file";
getUsefulContents(url,data=>doSomeThing(data););
default关键字:
export default function a(){};
等效于
export {a as default};
import a from “/d”;
等效于
import {default as a} from “/d”;
import $ ,{a,b,c} from “Jquery”;
$等效于{default as $}
as关键字
取别名