【重要】ES6-23 JavaScript模块化

  • 前端js模块化的演变发展
  • 模块化解决的问题
  • 传统模块化、插件化
  • CommonJS
  • AMD/CMD
  • ES6模块化

ES6以前 没有js引擎

  1. 一开始js写在html的script标签里
  2. js内容增多,抽取出index.js文件,外部引入
  3. js再增加,index.html对应index.js index2.html对应index2.js(模块化概念的诞生)
  4. 含有可复用的代码,提出公共的common.js
  5. 引入common.js的所有内容不合理 → 不能光以页面为基准来区分程序块、分js文件

案例一 模块化初试

// index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script type="text/javascript" src="js/module_a.js"></script><script type="text/javascript" src="js/module_b.js"></script><script type="text/javascript" src="js/module_c.js"></script><script type="text/javascript" src="js/index.js"></script>
</body>
</html>
// module_a.js
var a = [1, 2, 3, 4, 5].reverse()
// module_b.js
var b = a.concat([6, 7, 8, 9, 10])
// module_c.js
var c = b.join('-')
// index.js
console.log(a)
console.log(b)
console.log(c)

在这里插入图片描述

存在问题

  • js引擎遇到script时阻塞,所以这4个js文件必须按内部的逻辑,顺序加载,顺序是不能变的
  • 这4个文件共用了JS作用域-全局作用域
  • 因此:污染全局 + if 变量重名 → 变量覆盖

模块化解决问题:

  1. 加载顺序
  2. 污染全局

案例二 IIFE注入

历史问题:ECMA规定语句应当以分号结尾,早前js都是运行在浏览器上的,但浏览器支持判断当前是否是语句,是就自动加上分号。当使用多个IIFE,且不写分号时,浏览器无法识别,报错。因此约定俗成的规定,IIFE前面必须写分号,更规范的是结尾也写分号,即
;(function(){
})();

  1. 使用IIFE,解决污染全局,为了易于拓展,模块应当返回对象
  2. 新的问题,若没有抛到全局,如何在模块之间获得相应的abc
  3. 用变量接收IIFE的返回值,在需要用的的模块传入(注入),解决了模块依赖
  4. 注意:模块名完全独立,不应该重复,因此在全局声明了,而内部abc属于数据类型的变量,不能在全局声明
  5. 注意:不注入moduleABC,直接用moduleA.a访问变量能得到正确结果,但注入意味着moduleABC被引入到局部作用域下,不再需要去全局上查找了
// module_a.js
var moduleA = (function () {var a = [1, 2, 3, 4, 5].reverse()return {a: a}
})();
// module_b.js
var moduleB = (function (moduleA) {var b = moduleA.a.concat([6, 7, 8, 9, 10])return {b: b}
})(moduleA);
// module_c.js
var moduleC = (function (moduleB) {var c = moduleB.b.join('-')return {c: c}
})(moduleB);
// index.js
; (function (moduleA, moduleB, moduleC) {console.log(moduleA.a)console.log(moduleB.b)console.log(moduleC.c)
})(moduleA, moduleB, moduleC);

存在问题

  1. 顺序问题依然未解决

插件

  1. 构造函数执行init
  2. 构造函数挂载到window(插件)
  3. script里实例化
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

案例三 CommonJS

NodeJS诞生带来了前所未有的模块化体验
require(...) 引入模块
module.exports导出模块

运行在node环境下

CommonJS是模块化规范,来源于NodeJS
在服务端开发,引入模块用require,是同步的方法
只要引用,就会创建模块的实例
有非常强的缓存机制
一定是在Node上运行,客户端运行不了(要借助webpack?)
require实质是IIFE,会传入一些参数
(function(exports,require,module,__filename.__dirname){})()

  • CommonJS
  • 只引入index.js
// index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script type="text/javascript" src="index.js"></script>
</body>
</html>
// module_a.js
var a = (function () {return [1, 2, 3, 4, 5].reverse()
})();
module.exports = {a
};
// module_b.js
var moduleA = require('./module_a')
var b = (function () {return moduleA.a.concat([6, 7, 8, 9, 10])
})();
module.exports = {b
}
// module_c.js
var moduleB = require('./module_b')
var c = (function () {return moduleB.b.join('-')
})();
module.exports = {c: c
}
// index.js
var moduleA = require('./js/module_a.js');
var moduleB = require('./js/module_b.js');
var moduleC = require('./js/module_c.js');
; (function () {console.log(moduleA.a)console.log(moduleB.b)console.log(moduleC.c)
})()

案例四 AMD

  • 不需要借助webpack就能运行在客户端
  • 所有依赖加载完成后才会执行回调函数(前置依赖)

AMD Asynchronous Module Definition 异步模块定义
来源于CommonJS
define(moduleName, [module], factory) 定义模块
require([module], callback) 引入模块
RequireJS实现AMD

  1. 引入require.js
  2. 定义+使用依赖时注入
  3. 使用module得先require.config配置路径
// index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script src="js/require.js"></script><script src="js/index.js"></script>
</body>
</html>
// module_a.js
define('moduleA', function () {var a = [[1, 2, 3, 4, 5]]return {a: a.reverse()}
})
// module_b.js
define('moduleB', ['moduleA'], function (moduleA) {return {b: moduleA.a.concat([6, 7, 8, 9, 10])}
})
// module_c.js
define('moduleC', ['moduleB'], function (moduleB) {return {c: moduleB.b.join('-')}
})
// index.js
require.config({paths: {moduleA: 'js/module_a',moduleB: 'js/module_b',moduleC: 'js/module_c'}
})
require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC) {console.log(moduleA.a)console.log(moduleB.b)console.log(moduleC.c)
});

案例五CMD

  • 阿里对模块化的贡献
  • require加载 define定义
  • exports导出(return和它的效果一直) module操作
  • 需要配置模块URL
  • 依赖加载完毕后执行factory
  • 依赖就近 按需加载(这是和CommonJS AMD本质上的不同)

Common Mudule Definition 通用模块定义
define(function(require,exports,module){}) 定义模块
seajs.use([module路径],function(moduleA,moduleB,moduleC){}) 使用模块

// index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script src="js/sea.js"></script><script src="js/index.js"></script>
</body>
</html>
// module_a.js
define(function (require, exports, module) {var a = [[1, 2, 3, 4, 5]]return {a: a.reverse()}
})
// module_b.js
define(function (require, exports, module) {var moduleA = require('module_a')return {b: moduleA.a.concat([6, 7, 8, 9, 10])}
})
// module_c.js
define(function (require, exports, module) {var moduleB = require('module_b')return {c: moduleB.b.join('-')}
})
// index.js
seajs.use(['module_a.js', 'module_b.js', 'module_c.js'], function (moduleA, moduleB, moduleC) {console.log(moduleA.a)console.log(moduleB.b)console.log(moduleC.c)
})

案例六 ES6模块化规范

import module from ‘模块路径’ 导入模块
export module 导出模块

Uncaught SyntaxError: Cannot use import statement outside a module

调试过程中的报错解答

// index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script type="module" src="./js/index.js"></script>
</body>
</html>
// module_a.js
export default {a: [1, 2, 3, 4, 5].reverse()
}
// module_b.js
import moduleA from './module_a.js'
export default {b: moduleA.a.concat([6, 7, 8, 9, 10])
}
// module_c.js
import moduleB from './module_b.js'
export default {c: moduleB.b.join('-')
}
// index.js
import moduleA from './module_a.js'
import moduleB from './module_b.js'
import moduleC from './module_c.js'; (function (moduleA, moduleB, moduleC) {console.log(moduleA.a)console.log(moduleB.b)console.log(moduleC.c)
})(moduleA, moduleB, moduleC);

案例7 CommonJS与ES6的区别

  • 配置webpack
    在这里插入图片描述
    在这里插入图片描述
// export.js
exports.a = 0;
setTimeout(() => {console.log('来自export', ++exports.a)
}, 300);
// commonjs.js
const { a } = require('./export')
setTimeout(() => {console.log('来自commonjs', a)
}, 300);
// es6.js
import { a } from './export'
setTimeout(() => {console.log('来自es6', a) // a是只读的
}, 300);

在这里插入图片描述

  1. commonjs输出的是一个值的拷贝
  2. es6模块输出的是值的引用
  3. commonjs模块是在运行时加载(commonjs运行在服务端,require时加载)
  4. es6模块是在编译时加载

YUI

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/250963.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jquery --- 多选下拉框的移动(穿梭框)

效果如下: 几个注意地方: 1.多选下拉框需要添加 multiple 2.获取选中的元素KaTeX parse error: Expected EOF, got # at position 3: (#̲id option:selec…(#id option:not(:selected)) 下面是代码的各个部分实现, 方便引用,最后是总体代码,方便理解 添加选中到右边: // …

ES6-24 生成器与迭代器的应用

手写生成器 先done再false&#xff0c;不然index就提前了一步1 var arr [1,2] function generator(arr){var i 0;return{next(){var done i > arr.length ? true : false,value done ? undefined : arr[i];return {value : value,done : done} }} } var gen gener…

jquery --- 收缩兄弟元素

点击高亮的收缩兄弟元素. 思路: 1.点击的其实是tr.(类为parent) 2.toggleClass可以切换样式 3.slblings(’.class’).toggle 可以根据其类来进行隐藏显示 代码如下: <!DOCTYPE html> <html> <head> <meta charset"utf-8"><style>.pa…

Webpack基础

path.resolve // 只要以/开头&#xff0c;就变为绝对路径 // ./和直接写效果相同 var path require("path") //引入node的path模块path.resolve(/foo/bar, ./baz) // returns /foo/bar/baz path.resolve(/foo/bar, baz) // returns /foo/bar/baz path.res…

LeetCode:二叉树相关应用

LeetCode&#xff1a;二叉树相关应用 基础知识 617.归并两个二叉树 题目 Given two binary trees and imagine that when you put one of them to cover the other, some nodes of the two trees are overlapped while the others are not. You need to merge them into a new …

jquery --- 网页选项卡

点击,不同的tab_menu,显示不同的tab_box 注意点: 1.获取ul下,当前li的编号. $(‘div ul li’).index(this) 2.显示ul下编号为$index的li -> $(‘ul li’).eq($index) <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <style&g…

Webpack进阶(二)代码分割 Code Splitting

源代码index.js里包含2部分① 业务逻辑代码 1mb② 引入&#xff08;如lodash包&#xff09;的代码 1mb若更新了业务逻辑代码&#xff0c;但在浏览器运行时每次都下载2mb的index.js显然不合理&#xff0c;第三方包是不会变的 手动拆分 webpack.base.js entry: {main: path.re…

5177. 【NOIP2017提高组模拟6.28】TRAVEL (Standard IO)

Description Input Output Solution 有大佬说&#xff1a;可以用LCT做。&#xff08;会吗&#xff1f;不会&#xff09; 对于蒟蒻的我&#xff0c;只好用水法&#xff08;3s&#xff0c;不虚&#xff09;。 首先选出的泡泡怪一定是连续的一段 L&#xff0c; R 然后 L 一定属于虫…

python 3.x 爬虫基础---http headers详解

python 3.x 爬虫基础 python 3.x 爬虫基础---http headers详解 python 3.x 爬虫基础---Urllib详解 python 3.x 爬虫基础---Requersts,BeautifulSoup4&#xff08;bs4&#xff09; python 3.x 爬虫基础---正则表达式 前言  上一篇文章 python 爬虫入门案例----爬取某站上海租房…

Webpack进阶(三)

懒加载 lazy loading 用到的时候才加载vue 首屏不加载index.js const oBtn document.getElementById(j-button) oBtn.onclick async function () {const div await createElement()document.body.appendChild(div) } async function createElement() {const { default: _ …

P2634 [国家集训队]聪聪可可

链接&#xff1a;https://www.luogu.org/problemnew/show/P2634 题目描述 聪聪和可可是兄弟俩&#xff0c;他们俩经常为了一些琐事打起来&#xff0c;例如家中只剩下最后一根冰棍而两人都想吃、两个人都想玩儿电脑&#xff08;可是他们家只有一台电脑&#xff09;……遇到这种问…

算法 --- 快慢指针判断链表是否有环

解题思路: 分别设置2个指针(s,q)指向链表的头部,s每次指向下面一个(s s.next),q每次指向下面2个(q q.next.next). 如果存在环,q总会在某一时刻追上s /*** Definition for singly-linked list.* function ListNode(val) {* this.val val;* this.next null;* }*//**…

node --- 使用nrm改变npm的源

说明: 1.nrm只是单纯的提供了几个常用的下载包的URL地址,方便我们再使用npm装包是 很方便的进行切换. 2.nrm提供的cnpm 和通过 cnpm装包是2个不同的东西(使用cnpm install必须先安装cnpm -> npm install -g cnpm) 安装nrm: // linux $ [sudo] npm install --global nrm// w…

MySQL教程(三)—— MySQL的安装与配置

1 安装MySQL 打开附件中的文件&#xff08;分别对应电脑系统为32/64位&#xff09;。点next。 三个选项&#xff0c;分别对应典型安装、自定义安装和完全安装&#xff0c;在此选择典型安装&#xff08;初学者&#xff09;。 点install。 广告&#xff0c;忽略它。 安装完成…

c++ --- 字符串中的标点符号

题外话: 最近看node,发现node中好多强大的功能都设计到C,为了加深对node的理解,开始简单的学习一下C语法 ispunct: 统计string对象中标点符号的个数 #include <iostream> using namespace std; int main () {string s ("Hello World!");decltype(s.size()) p…

Hadoop(5)-Hive

在Hadoop的存储处理方面提供了两种不同的机制&#xff0c;一种是之前介绍过的Hbase&#xff0c;另外一种就是Hive&#xff0c;有关于Hbase&#xff0c;它是一种nosql数据库的一种&#xff0c;是一种数据库&#xff0c;基于分布式的列式存储&#xff0c;适合海量数据的操作&…

认识及实现MVC

gitee M&#xff1a;Model 数据模型&#xff08;模型层&#xff09;→ 操作数据库&#xff08;对数据进行增删改查&#xff09; V&#xff1a;View视图层 → 显示视图或视图模板 C&#xff1a;Controller 控制器层 → 逻辑层 数据和视图关联挂载和基本的逻辑操作 API层 前端请…

算法 --- 翻转二叉树

解(C): 1.二叉树判空 if(root 0) 或 if(root nullptr); 2.二叉树的左子树: root->left . 3.使用递归,将当前根节点的左右指针指向互换左向右子树(此时右子树也进行了翻转) // C /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode…

float 常见用法与问题--摘抄

float 属性绝对是众多切图仔用的最多的 CSS 属性之一&#xff0c;它的用法很简单&#xff0c;常用值就 left、right、none 三个&#xff0c;但是它的特性你真的弄懂了吗&#xff1f; 我会在这里介绍我对 float 的认识与使用&#xff0c;以及使用过程中遇到的问题。 对 float 的…

javascipt -- find方法和findIndex方法的实现

find: 根据传入的条件函数,返回符合条件的第一项 var arr [{id: 1, name: zs, age: 18},{id: 2, name: zs, age: 17},{id: 3, name: ls, age: 16},{id: 4, name: ls, age: 15}]Array.prototype._find_ function(cb){for(var i0; i< this.length; i){if(cb(this[i],i)){ret…