首先看看下面面试题
1、 const result=require('./index');//假如有这个文件,但文件啥都没有
console.log(result);
console.log(this);
console.log(module.exports);
console.log(exports);
//在node环境中输出你会发现打印的结果都为:{},而且都相等
2、再看这个
console.log(this===exports);
console.log(this===module.exports);
exports.c=3;
module.exports={
a:1,
b:2
};
this.m=5;
console.log(this);
console.log(this===exports);
console.log(this===module.exports);
console.log(module.exports);
//打印的结果为 this为:{c:3,m:5};
this===exports结果为true;
this===module.exports结果为false;
module.exports为:{a:1,b:2}
铺垫一下基础
//不可改变的原始值:栈
let a=1;
let b=a;
a=3;
console.log(a);//3
console.log(b);//1
b=4;
console.log(b);//4
//栈:定义一个名字a指向一个房间,房间里面放了一个值为1;
定义一个b指向和a相同的房间;
重新定义一个房间值为3,把原来的a指向新的房间;所以为什么打印a的值为什么是3;
b的指向还是原来a指向的房间,所以打印b的值为1;如果改变b的值:b=4;再创建一个新房间值为4,然后把b指向新房间,所以最终打印的a为4
//引用值存在堆 栈和堆
let a={};
let b=a;
a.c=3;
console.log(a);//{c:3}
console.log(b);//{c:3}
b={d:4};
console.log(a);//{c:3}
console.log(b);//{d:4}
//在栈里面创建一个名字叫a的房间,然后堆里面创建一个名字(地址)为heapA的房间值为一个空对象{},a房间的值为堆房间的名字(地址)heapA;
//在栈里面新创建一个房间名字叫b,b房间的值为a房间的值为heapA,和a房间指向相同的堆房间;
//此时向a房间添加东西,a房间发现地址指向heapA,就去改变堆里面房间heapA的值,空对象{}添加c属性值为3,此时heapA房间的值为{c:3};
//所以此时访问a和b都指向同一个房间heapA,所以值都是{c:3};
//当改变b的值的时候,相当于在堆里面重新创建一个房间叫heapB值为{d:4};然后把b的引用地址改成新的heapB,所以打印b的时候是{d:4},而a不变;
//所以引用值,只要你改变值,就会创建一个新的堆房间,指向原来房间的地址不变则值不变,如果改变引用值指向新的堆房间,值则是新的堆房间的值
简单剖析一下require函数【commonjs是必须在函数环境下运行】
function require(modulePath){
//1、将modulePath转换为绝对路径:D:\\\\MyProject\\\\homeWork\\\\node\\\\index.js;
//2、判断是否该模块已有缓存
// if(require.cache['D:\\\\\\\\MyProject\\\\\\\\homeWork\\\\\\\\node\\\\\\\\index.js']){
// return require.cache['D:\\\\\\\\MyProject\\\\\\\\homeWork\\\\\\\\node\\\\\\\\index.js'].result;
// }
//3、读取文件内容
//4、包裹到一个函数中
function __temp(module,exports,require,__dirname,__filename) {
//.....
}
//6.创建module对象 ------重点
module.exports={};
const exports=module.exports;
//执行读取文件函数
__temp.call(module.exports,module,exports,require,module.path,module.filename)
//最终返回module.exports
return module.exports;
}
//定义缓存对象
require.cache={};
//解释:在读取文件的时候,内部会调用访问文件函数:__temp.call(module.exports,module,exports,require,module.path,module.filename)
//在访问模块的时候this指向的是module.exports,而module.exports为一个空对象,exports等于module.exports
//所以为什么开头一开始问什么打印的全部都是空对象
//require函数返回的是module.exports,此时返回的是一个空对象{}
//exports值也是空对象{},当给exports赋值时:exports.c=3;
//此时值为一个引用值,相当于改变了堆房间的值,但是引用堆房间的地址不变,所以修改exports的值module.exports也会改变,还是空对象{c:3},此时的this也是{c:3}
//module.exports={a:1,b:2};现在是改变了值,就相当于在堆中创建了一个新的房间,然后指向新的房间,
//所以this指向的还是原来的房间,故this与module.exports不相等,但是this和exports还是相等的
//所以在访问模块的时候this表示exports