JavaScript 中的模块化
JavaScript 中的模块化
最早的基于立即执行函数,闭包的模块化
const MountClickModule = function(){
let num = 0;
const handleClick = ()=>{
console.log(++num);
}
return {
countClick:()=>{
document.addEventListener('click',handleClick)
}
}
}();
MountClickModule.countClick();
(function(module) {
module.say = ()=>{
console.log(num) //undefined
//do something
}
})(MountClickModule);
MountClickModule.say();
这种闭包的坏处:
- 扩展模块间无法访问私有变量。
- 强依赖模块导入的顺序,项目变大后不好维护。
AMD 和 CommonJS 模块化JavaScript 应用
AMD 和 CommonJS 是两个互相竞争的标准,均可定义 JavaScript 模块。除了语法和原理的区别之外,主要区别是 AMD 的设计理念是明确基于浏览器,而 CommonJS 的设计是面向通用 JavaScript 环境
使用 AMD 定义模块依赖
AMD 异步模块定义规范制定了定义模块的规则,这样模块和模块的依赖可以被异步加载。这和浏览器的异步加载模块的环境刚好适应(浏览器同步加载模块会导致性能、可用性、调试和跨域访问等问题)。
目前,AMD 最流行的实现是 RequireJS
。
define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
exports.verb = function() {
return beta.verb();
//Or:
return require("beta").verb();
}
});
AMD 提供名为 aplha 的函数,它接收一下参数:
- 第一个参数,
id
,是个字符串。它指的是定义中模块的名字,这个参数是可选的。如果没有提供该参数,模块的名字应该默认为模块加载器请求的指定脚本的名字。 - 第二个参数,dependencies,是个定义中模块所依赖模块的数组。
- 第三个参数是初始化模块的工厂函数,该函数接收dependencies作为参数 AMD异步获取依赖,以避免阻塞,如果依赖来自服务器,那么这个过程将花费一些时间,知道依赖全部加载完成后,调用模块的工厂函数,并传入所有的依赖。
可以看出,AMD 有一下几项有点:
- 异步加载模块,避免阻塞。
- 自动处理依赖,我们无需考虑模块的引入顺序。
- 在同一个文件中可以定义多个模块。
CMD
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出,在 CMD 规范中,一个模块就是一个文件。代码的书写格式如下:
define(function (require, exports, module) {
const foo = require('./foo')
a.doSomething()
// ...
const bar = require('./bar') // 依赖可以就近书写
b.doSomething()
// do something else
})
CommonJS
AMD 的设计明确基于浏览器,而 CommonJS 的设计是面向通用 JavaScript 环境。CommonJS 目前在 Nodejs 社区中具有最多的用户。CommonJS 使用基于文件的模块,所以每个文件中都只能定义一个模块,CommonJs 提供变量 module,该变量具有属性 exports,通过 exports 很容易扩展属性。最后,module.exports 作为模块的公共接口。
const beta = require('beta');
function alpha(){
return beta.verb();
//Or:
return require("beta").verb();
}
module.exports = alpha;
CommonJS 要求一个文件就是一个模块,文件中的代码就是模块的一部分,所以不需要使用立即执行函数来包装变量,在模块中定义的变量都是安全的再模块中,不会泄露到全局作用域。只有通过 module.exports
对象暴露的对象或函数才可以在函数外部访问 CommonJS 具有以下特点:
- 基于文件系统。
- 引入模块时文件同步加载,可以访问模块的公共接口。
- 模块加载相对更快 这是 CommonJS 在服务端更流行的原因。
ES6 模块的导入导出
ES6 模块结合了CommonJS 和 AMD 的有点,具体如下:
- 与 CommonJS 类似,ES6模块语法相对简单,并且基于文件(每一个文件就是一个模块)
- 与 AMD 类似,ES6 模块支持异步加载模块。
既 ES6 结合了两种模块化的有点,基于文件系统,既支持异步也支持同步,因为浏览器并没有实现 ES6 的模块化 API 所以具体是异步还是同步取决于loader api
ES6 模块的主要思想是必须显示的使用标志符导出模块,才能从外部访问模块。其他标志符,甚至在最顶级作用域中定义的标识符,只能在模块中使用。 ES6 引入两个关键字:
- export ---- 从模块外部指定标识符。
- import ---- 导入模块标识符。
从index.js模块中导出:
const hello = 'hello';
export const name = 'yunfly'
export function sayHi(){
return `${hello} ${name}!`
}
也可以在模块最后一起导出:
// foo.js
const hello = 'hello';
export const name = 'yunfly'
export function sayHi(){
return `${hello} ${name}!`
}
export { name, sayHi }
// export { name as firstName, sayHi }
// bar.js
// 使用 as 设置导如别名
import { name as firstName, sayHi } from 'foo'
console.log(name)
sayHi()
//bar2.js
// 导出全部标识符:
import * as sayModule from 'foo';
console.log(sayModule.name)
sayModule.sayHi()
// foo.js
class Foo {}
export default Foo
// bar.js
import Foo from './foo';
这存在一些可维护性的问题:
- 如果你在 foo.ts 里重构 Foo,在 bar.ts 文件中,它将不会被重新命名;
- 如果你最终需要从 foo.ts 文件中导出更多有用的信息(在你的很多文件中都存在这种情景),那么你必须兼顾导入语法。
- 在 ts 中默认导出的可发现性非常差,你不能智能的辨别一个模块它是否有默认导出。
文章参考:《JavaScript忍者秘籍》
JavaScript 中的模块化的更多相关文章
- 简单聊一聊Javascript中的模块化
在面试中只要说到模块化的问题,多多少少总会问到这些,umd.amd.cjs.esm,可能听过其中一个两个,或者都听说过.接下来我们先简单了解一下他们到底是什么,又有什么样的区别呢. 最开始的时候,Ja ...
- JavaScript中的模块化之AMD和CMD
前言: 为什么我们需要模块化开发,模块化开发的好处有哪些? 首先我们先说一下非模块化的开发方式带来的弊端. 非模块化开发中会导致一些问题的出现,变量和函数命名可能相同,会造成变量污染和冲突,并且出错时 ...
- JavaScript中为什么使用立即执行函数来封装模块?
最近在学习JavaScript基础,在学习到面向对象编程时,学习到在JavaScript中实现模块化的方法,其中一个重要的点是如何封装私有变量. 实现封装私有变量的方法主要是: 使用构造函数 func ...
- javascript中模块化知识总结
JavaScript 模块化开发 1. 模块化介绍 掌握模块化基本概念以及使用模块化带来的好处 当你的网站开发越来越复杂的时候,会经常遇到什么问题? 恼人的命名冲突 繁琐的文件依赖 历史上,JavaS ...
- JavaScript 中的数据类型
Javascript中的数据类型有以下几种情况: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Function,Date,Ar ...
- 【总结】浅谈JavaScript中的接口
一.什么是接口 接口是面向对象JavaScript程序员的工具箱中最有用的工具之一.在设计模式中提出的可重用的面向对象设计的原则之一就是“针对接口编程而不是实现编程”,即我们所说的面向接口编程,这个概 ...
- JavaScript中的函数表达式
在JavaScript中,函数是个非常重要的对象,函数通常有三种表现形式:函数声明,函数表达式和函数构造器创建的函数. 本文中主要看看函数表达式及其相关的知识点. 函数表达式 首先,看看函数表达式的表 ...
- 理解和使用 JavaScript 中的回调函数
理解和使用 JavaScript 中的回调函数 标签: 回调函数指针js 2014-11-25 01:20 11506人阅读 评论(4) 收藏 举报 分类: JavaScript(4) 目录( ...
- [转]Javascript中的自执行函数表达式
[转]Javascript中的自执行函数表达式 本文转载自:http://www.ghugo.com/javascript-auto-run-function/ 以下是正文: Posted on 20 ...
随机推荐
- Java基础Day07(Map Calender Date 包装类 System类 异常)
1.Map Map是集合容器,存放的元素有键与值两部分组成,通过键可以找到所对应的值,键和值必须是引用数据类型,键是唯一的,不能重复,没有顺序. HashMap是Map的实现类. Map的添加,删除, ...
- 网页不让用户复制方法总汇,设置html禁止选择,保护源码,js禁止复制文字
这篇文章主要讲解:右键复制失效方法.菜单"文件"-"另存为"失效方法.防止查看源代码进行复制的方法.防止页面缓存的方法.来达到一定的代码保护效果 右键复制失效方 ...
- 2020最新的Spring Boot 分布式锁的具体实现(内附代码)
前言 面试总是会被问到有没有用过分布式锁.redis 锁,大部分读者平时很少接触到,所以只能很无奈的回答 "没有".本文通过 Spring Boot 整合 redisson 来实现 ...
- [JAVA]移位运算(左移<<,右移>>和无符号右移>>>)
一.背景知识 整数在内存中是以二进制的形式存在的,而且存的是该整数的补码.最高位代表符号位,正数为0,负数为1 正数的补码是其二进制本身,负数的补码则是 符号位保持1不变,其他位按位取反再加1,+0和 ...
- day56 js收尾,jQuery前戏
目录 一.原生js事件绑定 1 开关灯案例 2 input框获取焦点,失去焦点案例 3 实现展示当前时间,定时功能 4 省市联动 二.jQuery入门 1 jQuery的两种导入方式 1.1 直接下载 ...
- 读《大话设计模式》——应用工厂模式的"商场收银系统"(WinForm)
要做的是一个商场收银软件,营业员根据客户购买商品单价和数量,向客户收费.两个文本框,输入单价和数量,再用个列表框来记录商品的合计,最终用一个按钮来算出总额就可以了,还需要一个重置按钮来重新开始. 核心 ...
- 解决redis秒杀超卖的问题
我们再使用redis做秒杀程序的时候,解决超卖问题,是重中之重.以下是一个思路. 用上述思路去做的话,我们再用户点击秒杀的时候,只需要检测,kucun_count中是否能pop出数据,如果能pop出来 ...
- 索引中丢失 IN 或 OUT 参数:: 103,解决办法
索引中丢失 IN 或 OUT 参数:: 103 这个原因是数据库中的字段类型与SQL语句中的类型不匹配造成的,103代表第103个字段参数错误.找到对应参数配置或者SQL中这个参数的类型是否与数据库 ...
- C#数据结构与算法系列(二十二):快速排序算法(QuickSort)
1.介绍 快速排序(QuickSort)是对冒泡排序的一种改进,基本思想是:通过一趟排序将要排序的数据分割成独立的两部分, 其中一部分的所有数据都比另一部分的所有数据都要小,然后再按此方法对这两部分数 ...
- Python Ethical Hacking - VULNERABILITY SCANNER(6)
EXPLOITATION - XSS VULNS EXPLOITING XSS Run any javascript code. Beef framework can be used to hook ...