require 的运行机制和缓存策略你了解吗?
require 加载模块的是同步还是异步?谈谈你的理解
exports 和 module.exports 的区别是什么?
require 加载模块的时候加载的究竟是什么?
提到 exports 和 module.exports 我们不得不提到 require 关键字。大家都知道 Node.js 遵循 CommonJS 规范,使用 require 关键字来加载模块。
问题:不知道小伙伴们在使用 require 引入模块的时候有没有相关,多个代码文件中多次引入相同的模块会不会造成重复呢?
因为在 C++ 中通常使用#IFNDEF等关键字来避免文件的重复引入,但是在 Node.js 中无需关心这一点,因为 Node.js 默认先从缓存中加载模块,一个模块被加载一次之后,就会在缓存中维持一个副本,如果遇到重复加载的模块会直接提取缓存中的副本,也就是说在任何时候每个模块都只在缓存中有一个实例。
先回答问题,同步的!
但是面试官要是问你为什么是同步还是异步的呢?
其实这个答案并不是固定的,但是小伙伴们可以通过这几方面给面试官解释。
Node.js 会自动缓存经过 require 引入的文件,使得下次再引入不需要经过文件系统而是直接从缓存中读取。不过这种缓存方式是经过文件路径定位的,即使两个完全相同的文件,但是位于不同的路径下,会在缓存中维持两份。
可以通过
console.log(require.cache)
获取目前在缓存中的所有文件。
在一个 node 执行一个文件时,会给这个文件内生成一个 exports 和 module 对象,
而module又有一个 exports 属性。他们之间的关系如下图,都指向一块{}内存区域。
exports = module.exports = {};
看一张图理解这里更清楚:
require()加载模块的时候我们来看一段实例代码
//koala.js
let a = '程序员成长指北';
console.log(module.exports); //能打印出结果为:{}
console.log(exports); //能打印出结果为:{}
exports.a = '程序员成长指北哦哦'; //这里辛苦劳作帮 module.exports 的内容给改成 {a : '程序员成长指北哦哦'}
exports = '指向其他内存区'; //这里把exports的指向指走
//test.js
const a = require('/koala');
console.log(a) // 打印为 {a : '程序员成长指北哦哦'}
看上面代码的打印结果,应该能得到这样的结论:
require导出的内容是module.exports的指向的内存块内容,并不是exports的。
简而言之,区分他们之间的区别就是 exports 只是 module.exports的引用,辅助后者添加内容用的。用内存指向的方式更好理解。
看一下官方文档中exports的应用
我们经常看到这样的写法:
exports = module.exports = somethings
上面的代码等价于:
module.exports = somethings
exports = module.exports
原理很简单,即 module.exports 指向新的对象时,exports 断开了与 module.exports 的引用,那么通过 exports = module.exports 让 exports 重新指向 module.exports 即可。
建议:在使用的时候更建议大家使用module.exports(根据下面的例子也能得出)
Node.js 认为每个文件都是一个独立的模块。如果你的包有两个文件,假设是“a.js” 和“b.js”,然后“b.js” 要使用“a.js” 的功能,“a.js” 必须要通过给 exports 对象增加属性来暴露这些功能:
// a.js
exports.verifyPassword = function(user, password, done) { ... }
完成这步后,所有需要“a.js” 的都会获得一个带有“verifyPassword” 函数属性的对象:
// b.js
require(‘a.js’) // { verifyPassword: function(user, password, done) { ... } }
然而,如果我们想直接暴露这个函数,而不是让它作为某些对象的属性呢?我们可以覆写 exports 来达到目的,但是我们绝对不能把它当做一个全局变量:
// a.js
module.exports = function(user, password, done) { ... }
注意到我们是把“exports” 当做 module 对象的一个属性。“module.exports” 和“exports” 这之间区别是很重要的,而且经常会使 Node.js 新手踩坑。
require 和 import 区别:遵循的模块化规范不一样,出现的时间不同。Require是CommonJS的语法,CommonJS的模块是对象,输入时必须查找对象属性。
需求:如何components里面的index.vue怎样能把assets里面的图片拿出来。 1.在img标签里面直接写上路径,2.利用数组保存再循环输出
为什么会突然用到webpack这个管理特性呢?项目某个页面需要引入N张demo图片。即资源的批量引入:如果要引入10+个以上的图片资源,就需要写10+个如下的引入代码:import XXX from ;,那如果再多一点的静态资源需要引入呢?这时候require.context就派上了用场。
RequireJS是一个工具库,主要用于客户端的模块管理。它可以让客户端的代码分成一个个模块,实现异步或动态加载,从而提高代码的性能和可维护性。它的模块管理遵守AMD规范,模块与模块之间可以互相依赖,当然可能会有人会想,模块之间的依赖
Node应用由模块组成,采用CommonJS模块规范。根据这个规范,每个文件就是一个模块,有自己的作用域。在这些文件里面定义的变量、函数、类,都是私有的,对外不可见,因此规避掉了作用域污染。
当前端应用越来越复杂时,我们想要将代码分割成不同的模块,便于复用、按需加载等。require 和 import 分别是不同模块化规范下引入模块的语句,下文将介绍这两种方式的不同之处。
在项目中用 require(./Download.vue) 引入一个组件的时缺少.default 会报错:Failed to mount component: template or render function not defined
我们常说node并不是一门新的编程语言,他只是javascript的运行时,运行时你可以简单地理解为运行javascript的环境。在大多数情况下我们会在浏览器中去运行javascript,有了node的出现
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境。早期的 Node.js 采用的是 CommonJS 模块规范,从 Node v13.2.0 版本开始正式支持 ES Modules 特性
人们常说node并不是一门新的编程语言,他只是javascript的运行时,运行时你可以简单地理解为运行javascript的环境。在大多数情况下会在浏览器中去运行javascript,有了node的出现,可以在node中去运行javascript
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!