一、前言 上一篇《前端科普系列(2):Node.js 换个角度看世界》,我们聊了 Node.js 相关的东西,Node.js 能在诞生后火到如此一塌糊涂,离不开它成熟的模块化实现,Node.js 的模块化是在...// a.js var name = 'morrain' var age = 18 上面代码中,a.js 是 Node.js 应用中的一个模块,里面申明的变量 name 和 age 是 a.js 私有的...你可以理解为 Node.js 在每个模块开始的地方,添加了如下这行代码。...原因主要有两个,一个是因为 Node.js 本身也不是完全采用 CommonJS 的规范,譬如在CommonJS 之 exports 中的提到 exports 属性就是 Node.js 自己加的,Node.js...前面提到的 Node.js 已经默认支持 ES6 Module ,浏览器也已经全面支持 ES6 Module。至于 Node.js 和 浏览器 如何使用 ES6 Module,可以自行学习。
换个角度看世界》,我们聊了 Node.js 相关的东西,Node.js 能在诞生后火到如此一塌糊涂,离不开它成熟的模块化实现,Node.js 的模块化是在 CommonJS 规范的基础上实现的。...// a.js var name = 'morrain' var age = 18 上面代码中,a.js 是 Node.js 应用中的一个模块,里面申明的变量 name 和 age 是 a.js 私有的...事实也是如些,早在2013年5月,Node.js 的包管理器 NPM 的作者 Isaac Z. Schlueter 说过 CommonJS 已经过时,Node.js 的内核开发者已经决定废弃该规范。...原因主要有两个,一个是因为 Node.js 本身也不是完全采用 CommonJS 的规范,譬如在CommonJS 之 exports 中的提到 exports 属性就是 Node.js 自己加的,Node.js...前面提到的 Node.js 已经默认支持 ES6 Module ,浏览器也已经全面支持 ES6 Module。至于 Node.js 和 浏览器 如何使用 ES6 Module,可以自行学习。
$ node main.js 在 b.js 之中,a.done = false b.js 执行完毕 在 a.js 之中,b.done = true a.js 执行完毕 在 main.js 之中, a.done...$ babel-node m2.js bar baz 上面代码表明,ES6模块不会缓存运行结果,而是动态地去被加载的模块取值,以及变量总是绑定其所在的模块。...$ babel-node a.js 执行完毕 a.js之所以能够执行,原因就在于ES6加载的变量,都是动态引用其所在的模块。只要引用是存在的,代码就能执行。...$ babel-node > import * as m from '....$ node > var m = require('./even'); > m.even(10) TypeError: even is not a function
$ node main.js 在 b.js 之中,a.done = false b.js 执行完毕 在 a.js 之中,b.done = true a.js 执行完毕 在 main.js 之中, a.done...$ babel-node m2.js bar baz 上面代码表明,ES6模块不会缓存运行结果,而是动态地去被加载的模块取值,以及变量总是绑定其所在的模块。...$ babel-node a.js 执行完毕 a.js之所以能够执行,原因就在于ES6加载的变量,都是动态引用其所在的模块。只要引用是存在的,代码就能执行。...$ babel-node > import * as m from '....$ node > var m = require('.
在浏览器,会使用 HTML 的规范,最后的实例化是同步,在 node 环境,文件都是在本地,同步就显得很容易。.../a.js'); 检查缓存,没有 a.js,执行 a.js a.js,检查缓存,没有,缓存 a.js。执行 let b = require('....node 执行 ES module 如果文件后缀是.mjs(node 执行的后缀是.cjs),那么 node 会根据 ES module 规范去执行,如果是 js,那么 package.json 里面要新增...,找不到依次往上的目录寻找 node_modules,直到根目录,还找不到就报错。...会先以文件名找,再依次是.js、.json、.node。
/a.js'); console.log(a2.foo); // 2 console.log(a1 === a2); // true 以上例子中,require a.js 并修改其中的 foo 属性...,接着再次 require a.js 可以看到两次 require 结果是一样的。...a.js': Module { id: '/Users/evan/Desktop/demo/a.js', exports: { foo: 1 },.../a.js') 时 是不能直接读取到 default 上的值的,为了和 ES6 中 import a from './a.js'的行为一致,会基于 __esModule 判断处理。.../a.js' 时,es module 预期的是返回 export 的内容。
/a.js'); a1.foo = 2; const a2 = require('..../a.js'); console.log(a2.foo); // 2 console.log(a1 === a2); // true 执行 node b.js,可以看到,第二次 require a.js.../a.js'); require('./a.js'); console.log(require.cache); 缓存中有两个key,分别是 a.js, b.js 文件在系统中的绝对路径。.../a.js') 的结果是 require.cache['/Users/helkyle/projects/learning-module/a.js'].exports 和第一次 require 指向的是同一个...'/Users/node_modules', '/node_modules' ] }, '/Users/helkyle/projects/learning-module/a.js
Node.js自定义模块 require是一个方法,它的作用就是用来加载模块的 在 Node中,模块有三种: 具名的核心模块,例如fs、 http 用户自己编写的文件模块 注意:相对路径必须加.../b') 案例1:在 a.js 中加载执行 b.js a.js console. log('a start') require('....案例2:a.js 中加载 b.js 、c.js a.js console. log('a start') require('....require就是加载执行文件中的代码 在 Node 中,没有全局作用域,只有模块作用域 外部访问不到内部 内部也访问不到外部 默认都是封闭的 既然是模块作用域,那如何让模块与模块之间进行通信 有时候,...案例5:调用b.js中的 age 的值 a.js var bExports = require('.
,参考:模块加载机制 module.exports与exports的区别,参考:对象引用关系考察 假设有a.js、b.js两个模块相互引用,会有什么问题?是否为陷入死循环?...模块循环引用 问题1 假设有 a.js、b.js 两个模块相互引用,会有什么问题?是否为陷入死循环?...看以下例子 // a.js console.log('a模块start'); exports.test = 1; undeclaredVariable = 'a模块未声明变量' const b =...控制台执行 node a.js,查看输出结果: a模块start b模块start undeclaredVariable: a模块未声明变量 b模块加载完毕: a.test值: 1 a模块加载完毕:...b.test值: 2 问题1,启动 a.js 的时候,会加载 b.js,那么在 b.js 中又加载了 a.js,但是此时 a.js 模块还没有执行完,返回的是一个 a.js 模块的 exports 对象
Node加载 概述 Node对ES6模块的处理比较麻烦,因为它有自己的CommonJS模块格式,与ES6模块格式是不兼容的。...让我们来看一下Node官方文档(nodejs.org/api/modules.html#modules_cycles)里面的例子。脚本文件a.js代码如下。...``` $ node main.js ``` ``` 在 b.js 之中,a.done = false b.js 执行完毕 在 a.js 之中,b.done = true a.js 执行完毕 在...执行a.js,结果如下。 ``` $ babel-node a.js b.js undefined a.js Bar ``` 上面的代码中,由于a.js的第一行是加载b.js,所以先执行的是b.js。...``` $ babel-node a.js foo bar 执行完毕 // 执行结果也有可能是 foo bar foo bar 执行完毕 执行完毕 ``` 上面的代码中,a.js之所以能够执行,原因就在于
新建一个脚本文件 a.js 。...$ node a.js module.id: . module.exports: {} module.parent: null module.filename: /home/ruanyf/tmp.../a.js module.loaded: false module.children: [] module.paths: [ '/home/ruanyf/tmp/node_modules',...新建另一个脚本文件 b.js,让其调用 a.js 。 // b.js var a = require('./a.js'); 运行 b.js 。.../node_modules', '/home/ruanyf/node_modules', '/home/node_modules', '/node_modules' ] 上面代码中,由于 a.js
1.清除a.js的内容 ➜ commands git:(master) ✗ cat a.js // There are two lines of code in a.js const a = 'fatfish...git:(master) ✗ cat a.js // The content in a.js is cleared. ➜ commands git:(master) ✗ 2.将a.js的内容复制到b.js...➜ commands git:(master) ✗ which node /Users/dz0400229/.nvm/versions/node/v16.0.0/bin/node ➜ commands...git:(master) ✗ which npm /Users/dz0400229/.nvm/versions/node/v16.0.0/bin/npm ➜ commands git:(master...) ✗ which npx /Users/dz0400229/.nvm/versions/node/v16.0.0/bin/npx ➜ commands git:(master) ✗ 16.mkdir
,参考:模块加载机制 module.exports与exports的区别,参考:对象引用关系考察 假设有a.js、b.js两个模块相互引用,会有什么问题?是否为陷入死循环?...模块循环引用 问题1 假设有 a.js、b.js 两个模块相互引用,会有什么问题?是否为陷入死循环?...控制台执行 node a.js,查看输出结果: a模块startb模块startundeclaredVariable: a模块未声明变量b模块加载完毕: a.test值: 1a模块加载完毕: b.test...值: 2 问题1,启动 a.js 的时候,会加载 b.js,那么在 b.js 中又加载了 a.js,但是此时 a.js 模块还没有执行完,返回的是一个 a.js 模块的 exports 对象 未完成的副本...然后 b.js 完成加载之后将 exports 对象提供给了 a.js 模块 问题2,因为 undeclaredVariable 是一个未声明的变量,也就是一个挂在全局的变量,那么在其他地方当然是可以拿到的
2、Node.js的组成 JavaScript 由三部分组成,ECMAScript,DOM,BOM。...Node.js是由ECMAScript及Node 环境提供的一些附加API组成的,包括文件、网络、路径等等一些更加强大的 API。 image.png JavaScript可以运行在哪里?...在Node环境下执行代码,使用Node命令执行后缀为.js的文件即可 image.png 全局对象global 在浏览器中全局对象是window,在Node中全局对象是global。...Node中全局对象下有以下方法,可以在任何地方使用,global可以省略。...('test1='+test1);//bbbbbb; console test1 输出'bbbbbb';悲剧啊 2、命名冲突 //a.js 文件: function fun
大家哦读知道 Node.js 遵循 CommonJS 规范,使用 require 关键字来加载模块。...因为在 C++ 中通常使用#IFNDEF等关键字来避免文件的重复引入,但是在 Node.js 中无需关心这一点,因为 Node.js 默认先从缓存中加载模块,一个模块被加载一次之后,就会在缓存中维持一个副本...require() 的缓存策略 Node.js 会自动缓存经过 require 引入的文件,使得下次再引入不需要经过文件系统而是直接从缓存中读取。...使用的一点建议 建议:在使用的时候更建议大家使用module.exports(根据下面的例子也能得出) Node.js 认为每个文件都是一个独立的模块。...如果你的包有两个文件,假设是“a.js” 和“b.js”,然后“b.js” 要使用“a.js” 的功能,“a.js” 必须要通过给 exports 对象增加属性来暴露这些功能: // a.js exports.verifyPassword
,查找node_module目录,然后进去查找,如果没有node_module目录,则继续 往上一级目录执行,直到根目录为止。...因为它会先从加载代码所在路径的node_module目录开始查找,假设我们应用有如下目录: myAPP |--- foo.js |---node_modules |----depA...假设我们的代码模块之间存在如下循环依赖: 我们先创建a.js和b.js,a.js的内容如下: exports.loaded = false const b = my_require('..../a.js’),在执行时首先会把a.js对应的module对象进行缓存,对应的语句如下: my_require.cache[id] = module 这个缓存是代码没有产生死循环的原因。...然后执行LoadModule,这个函数会执行a.js中的代码,在a.js代码中,第一行为: exports.load = false 这句话执行后会使得它对应的module变为module.exports.load
/a.js') obj.setCount() console.log('b', obj.count) //node b.js //b 1 //a 2 //可以看出,count在b.js文件中复制了一份.../a.js') data.setCount() console.log('b', data.obj.count) //node b.js //b 2 //a 2 //从以上可以看出,a.js和b.js...代码如下: //a.js let a = 100; export {a}; //b.js import {a} from "./a.js"; a = 200; 上面的代码会报错; ?.../m1.js"; setcount(); console.log(count); // node b.js // b 2 // a 2 通过执行结果我们可以看到es6module引用基本类型是动态引用的.../a.js'; export function bar() { console.log('bar'); foo(); } // a.js import {bar} from '.
/a.js" type="module"> type会让浏览器知道这是ES6模块,且这相当于开启了defer属性,如果你又写了async属性那么就会采用async。.../a.js" type="module"> import {a} from '..../a.js'; console.log(a); a.js里面: export var a = 100; console.log('a.js' + a); 注意点: 模块内部变量外部不可见...Node对ES6采用的是分开处理,因为node有自己的commonjs,node规定,ES6 模块采用.mjs后缀文件名。...__dirname ES6可以加载commonjs的模块,node会自动把module.exports属性变成export default。
如果没有,在父级目录的 node_modules 查找,如果没有在父级目录的父级目录的 node_modules 中查找。 沿着路径向上递归,直到根目录下的 node_modules 目录。...在查找过程中,会找 package.json 下 main 属性指向的文件,如果没有 package.json ,在 node 环境下会以此查找 index.js ,index.json ,index.node.../b') console.log('node 入口文件') 接下来终端输入 node main.js 运行 main.js,效果如下: 5.jpg 从上面的运行结果可以得出以下结论: main.js...① 首先执行 node main.js ,那么开始执行第一行 require(a.js); ② 那么首先判断 a.js 有没有缓存,因为没有缓存,先加入缓存,然后执行文件 a.js (需要注意 是先加入缓存...⑦ 最后回到 main.js,打印 console.log('node 入口文件') 完成这个流程。
领取专属 10元无门槛券
手把手带您无忧上云