| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> JavaScript知识库 -> 两种模块化语法(module.exportsexportsrequire && exportimport) -> 正文阅读 |
|
[JavaScript知识库]两种模块化语法(module.exportsexportsrequire && exportimport) |
目录 模块CommonJs规范中规定了每一个文件都是一个模块。使用require导入的文件会形成一个属于自身的模块作用域,这样就不会在进行变量以及函数声明时会污染全局作用域。所有的变量和函数都只有模块自身能访问,对外不可见的。 举例:
在bar.js中通过require函数加载foo.js。运行之后输出的结果是‘bar’,这就说明了foo.js中的变量声明并不会影响bar.js。每个文件都拥有自己的作用域。 导出导出是一个模块对外暴露自身的唯一方式。在CommonJs中,通过module.exports可以导出模块中的内容。 举例:
CommonJs模块内部会有一个module对象用于存放当前模块的信息,可以理解为在每个模块的最开始中定义了以下对象:
CommonJs也支持另一种导出方式:exports。
在实现上,这段代码与上面的module.exports没有不同,其内在机制是将exports指向了module.exports。可以简单的理解为CommonJs在每个模块的开头默认添加了以下代码:
因此,为export.name赋值相当于在module.exports对象上添加了一个name属性。 Ⅰ、也很容易看出exports与module.exports只是指向同一个对象。所以对exports进行赋值操作,使其指向新的对象,就会失效了。 ingenious:由上面可以知道???即使require 导出后也无法改变模块对象!! 举例:
此时name属性并不会被导出。 Ⅱ、另外这两个方法,并不能一起运用。因为使用module.exports赋值就相当于使其指向新的对象。之前的exports赋值都会失效。 导入CommonJs使用require函数进行导入操作。 举例:
在bar.js中导入了foo.js,并调用了它的sayname函数。 当require一个模块时会有两种情况:
举例:
输出的是:
从上面代码看有两个地方都require了foo文件,但从结果看,只运行了一遍foo.js。 module对象中有一个loaded属性用于记录该模块是否被加载过。默认值为false,当模块第一次被加载时,会赋值为true,后面再次加载时会检查module.loaded是否为true,如果是,则直接返回结果,并不会再次执行代码。 require函数可以接受表达式,借助这个特性可以动态地制定模块的加载路径。 举例:
ES6ModuleCommonJs可以说是比较好的解决了模块的问题,但这些都只是由社区提出的规范,并不能算语言本身的特性。 到了2015年,ECMAScript6.0正式定义了JavaScript模块标准。从此 JavaScript 语言才具备了模块这一特性。 模块将前面CommonJs的例子,用ES6Module方式改写。
ES6Module也是将每个文件作为一个模块,每个模块拥有自身的作用域,不同的是导入、导出语句。import和export也是作为保留关键字在ES6版本加入了进来,而且ES6Module会自动采用严格模式。 导出在ES6Module中使用export命令来导出模块。export有两种形式:
1、命令导出
可以通过as关键字对变量重命名。 例如:
2、默认导出 默认导出只能有一个:
可以将export default理解为对外输出一个名为default的变量。 导入ES6Module使用import语法导入模块。 举例:
加载带有命令导出的模块时,import后面要跟一对大括号来将导入的变量名包裹起来,并且这写变量名需要与导出的变量名完全一致。导入变量的效果相当于在当前作用域下声明了这些变量,并且不可以对齐进行修改。 与命令导出类似,也可以通过as关键字对导入的变量重命名。 举例:
默认导入的例子:
CommonJs与ES6Module的区别对模块依赖的处理区别CommonJs与ES6Module最本质的区别在于前者对模块依赖的解决是动态的,而后者是静态的。
在CommonJs中,当模块A加载模块B时,会执行B的代码,将其module.exports对象作为require函数的返回值进行返回。并且requrie的模块路径可以动态指定,支持传入一个表示式,甚至可以使用if语句判断是否加载某个模块。所以CommonJs模块被执行前,并没有办法确定明确的依赖关系,模块的导入,导出发生在代码的运行阶段。 ES6Module的导入、导出语句都是声明式的,不支持导入的路径是一个表达式,并且导入、导出语句必须位于模块的顶层作用域。在ES6代码的编译阶段就可以分析出模块的依赖关系。 导入模块值的区别在导入一个模块时,对于CommonJs来说是得到了一个导出值的拷贝;而在ES6Module中则是值的动态映射,并且这个映射是只读的。 举例:
bar中的count是对foo中count的一份值拷贝,因此在调用add函数时,虽然更改了foo中count的值,但是并不会对bar中导入值造成更改。 另一方面拷贝值可以进行更改。 使用ES6Module进行改写
可以将映射关系理解为一面镜子,从镜子中可以实时观察到原有的事物,但不能操作镜子中的影像。 循环依赖的区别CommonJs中循环依赖的例子:
在控制台输出:
首先来梳理执行流程:
使用ES6Module重写上面例子:
结果是: 来自foo: undefined 来自bar:bar 在bar中同样无法得到foo正确的导出值,只不过和CommonJS默认导出一个空对象不同,这里获取到的是undefined。 结尾模块是程序设计的重要概念,希望上述内容能让你了解到前端模块的概念。详细的用法搜索官网或者书籍进行学习。书籍推荐 作者:zhangwinwin |
|
JavaScript知识库 最新文章 |
ES6的相关知识点 |
react 函数式组件 & react其他一些总结 |
Vue基础超详细 |
前端JS也可以连点成线(Vue中运用 AntVG6) |
Vue事件处理的基本使用 |
Vue后台项目的记录 (一) |
前后端分离vue跨域,devServer配置proxy代理 |
TypeScript |
初识vuex |
vue项目安装包指令收集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 11:21:15- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |