nodejs的一个经典面试题
this.d = 4;
exports.c = 3;
module.exports = {
a: 1,
b: 2
}
//module.exports.a = 1
//module.exports.b = 2
const a = require('./a.js')
console.log(a);
这里执行的结果是:
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
this.d = 4;
exports.c = 3;
//module.exports = {
// a: 1,
// b: 2
// }
module.exports.a = 1
module.exports.b = 2
const a = require('./a.js')
console.log(a);
这里执行的结果是:
这里仅仅只是两个的输出方式不一样就导致了不一样的结果,其原因是有关node的底层代码:
因为require执行的时候会经过以下几个步骤:
注意以下代码都是理论代码不能执行,只是用作分析
1.调用了resolve方法拼接成了一个绝对路径
function require(modulePath){
//模块路径
}
2.在cache部分判断该模块是否有缓存。cache是require函数的缓存区
if(require.cache["C:\\Users\\admin\\Desktop\\0315nodejs\\04.js"]){
return require.cache["C:\\Users\\admin\\Desktop\\0315nodejs\\04.js"]
}
3.读取目标文件内容
4.包裹到一个函数中去
function require(modulePath){
//模块路径
if(require.cache["C:\\Users\\admin\\Desktop\\0315nodejs\\04.js"]){
return require.cache["C:\\Users\\admin\\Desktop\\0315nodejs\\04.js"]
}
function _temp(module,exports,require,__dirname,__filename){
//在require目标对象的所有代码都在这个内部函数执行
this.d = 4;
exports.c = 3;
module.exports = {
a : 1,
b : 2
}
}
}
5.创建module.exports对象(重点)
function require(modulePath){
//模块路径
if(require.cache["C:\\Users\\admin\\Desktop\\0315nodejs\\04.js"]){
return require.cache["C:\\Users\\admin\\Desktop\\0315nodejs\\04.js"]
}
function _temp(module,exports,require,__dirname,__filename){
//在require目标对象的所有代码都在这个内部函数执行
this.d = 4;
exports.c = 3;
module.exports = {
a : 1,
b : 2
}
}
// 5.创建module.exports对象
module.exports = {
}
const exports = module.exports
_temp.call(module.exports,exports,require,__dirname,__filename)
return module.exports;
}
在执行内部函数_temp的时候它会通过call来改变this的指向将其指向module.exports同时创建module.exports对象,然后创建exports同时把module.exports赋值exports也就是说现在this、module.exports、exports其实是一个东西:
console.log(module.exports === exports)//true
console.log(module.exports === this)//true
最后返回module.exports;
所以说
this.d = 4;
exports.c = 3;
module.exports.a = 1
module.exports.b = 2
输出{d:4, c:3, a:1, b:2}是因为它们都在往module.exports里加东西;
但是
this.d = 4;
exports.c = 3;
module.exports = {
a: 1,
b: 2
}
这里就有问题了一开始本来就创建了个module.exports的空对象,现在有赋值了一个新的对象。这就导致了module.exports指向了一个新的地址
这里我画个图来表示
第一种情况:
第二种情况:
而require函数返回的是module.exports自然也就输出的是{a:1,b:2}了