ES6+ 模块化使用二
发布时间:2023-03-28 13:12:51 所属栏目:教程 来源:
导读:JavaScript 语言在很长一段时间是没有模块化的概念的,直到 Node.js 的诞生后,让 JavaScript 有能力编写服务端语言,对操作系统、网络、文件系统等等的复杂业务场景,使用模块化就是不可或缺。这样也把模块化的概念
JavaScript 语言在很长一段时间是没有模块化的概念的,直到 Node.js 的诞生后,让 JavaScript 有能力编写服务端语言,对操作系统、网络、文件系统等等的复杂业务场景,使用模块化就是不可或缺。这样也把模块化的概念带到了前端,而这时的客户端的功能也很复杂,急需一种可以拆分代码模块方便管理代码的一种模式。最终在社区的推动下 ES6 给出了 JavaScript 模块化的规范。 在 Node 模块中,Commonjs 规定每个文件就是一个模块,有它自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。 使用 module.exports 把需要暴露的内容导出,没有导出的在外面是访问不了的。 // a.js module.exports.name = 'imooc'; module.exports.fn = function(){} const age = ; 上面的代码中在 a.js 文件中相当于一个私有的作用域, module.exports 把 name 和 fn 两个变量导出,但是 age 没有导出,所以在外部是访问不了的。 为了方便 module.exports 也可以省略 module 直接使用 exports 进行导出操作: exports.a = 'hello' 使用 module.exports 时还可以整体导出,整体导出时不能简写 exports 。 module.exports = { name: 'imooc', fn:function(){} } 使用 require 用于导入其他模块暴露出来的内容。导出的内容是一个对象。 const a = require('./a'); console.log(a); // { name: 'imooc', fn: [Function (anonymous)] } 所有代码都运行在模块作用域,不会污染全局作用域。 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。 模块加载的顺序,按照其在代码中出现的顺序。 使用 import 命令加载 Commonjs 模块,Node 会自动将 module.exports 属性当作模块的默认输出,即等同于 export default // a.js module.exports = { foo: 'hello', bar: 'world' } // 在import引入时等同于 export default { foo: 'hello', bar: 'world' } Commonjs 模块是运行时确定输出接口,所以采用 import 命令加载 Commonjs 模块时,只能使用整体输入(*)。 import {readfile} from 'fs' //当'fs'为Commonjs模块时错误 // 整体输入 import * as express from 'express' const app = express.default(); require 命令加载 ES6 模块时,所有的输出接口都会成为输入对象的属性。 // es.js let foo = {bar : 'my-default'}; exxport default foo; foo = null; // cjs.js const es_namespace = require('./es') console.log(es_namespace.default);// {bar:'my-default'} 模块化在面试中经常会被问到,掌握其深层原理是回答这类问题的关键。下面是面试中参考的两道题,这里和大家分享一下,提供的答案仅供参考。 commonjs 规范与 es module 规范的区别? 两个规范的区别可以从以下几个方面来回答: 模块的导出和导入:commonjs 使用的是 module.exports 和 require;es module 使用的是 export 和 import; 模块的引入方式:commonjs 是动态引用;esmodule 是静态分析,export 和 import 只能出现在代码的顶层,在编译时就可以确定引用; 模块的引用类型:commonjs 对基本类型传递值,esmodule 对基本类型是传递引用; Commonjs 的 this 是当前模块,ES6 Module 的 this 是 undefined; 对 webpack 来说,想要支持 tree shaking,包必须采用 es module 规范。 JS 在加载时分为两个阶段:编译和执行,而 ES6 模块是在 编译时进行加载(也可以叫:静态加载),这使得静态分析成为可能。es module 自动采用严格模式,不管你有没有在模块头部加上 "use strict";。 题目:commonjs 规范的循环引用 这是一道经典的 commonjs 的面试题,分析下列这段代码,并解释原理。 //main.js var a = require('./a') console.log(a) // a.js module.exports.a = var b = require('./b') console.log(b) module.exports.a = // b.js module.exports.b = var a = require('./a') console.log(a) module.exports.b = 回答本题的核心就是要知道 require 后的模块是会被缓存的,还需要注意的是先加入缓存,然后再执行。这样在按照代码同步的执行顺序去分析代码就会很清晰。具体分析如下: 使用 node main.js 执行 main.js 文件内容; 执行 require('./a') 会将 a 模块加入缓存,然后执行 a 模块中的内容,执行权交到了 a 模块中,执行 a; 执行第一行将缓存的 a 值赋值为 1,然后执行第二行 require('./b') 把 b 模块加入缓存,并把执行权交到 b 模块中; b 模块中把 b 的值赋值为 11,在 require('./a') 时,是从缓存中取的值,这里就会在控制台打印 {a: 1},最后把缓存中的 b 值修改为 22,执行权交给上一级; 代码执行权回到 a 模块中,这时 b 从缓存中取的值是 22,控制台中打印 { b: 22 } ,最后把缓存中的 a 值修改为 2,执行权交给上一级; 代码执行回到 main 模块中,这时缓存中的 a 是 2,控制台中打印 { a: 2 } ,然后代码执行完毕。 本节主要学习了 Commonjs 的使用、在 Commonjs 和 ES Module 混用的一些问题,最后通过两道面试题学习了两个规范的区别和 Commonjs 在使用时会存在循环引用的问题,并分析了其执行的顺序和缓存的特点。 (编辑:汽车网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |