以CommonJS在node中的实现为例介绍js中的对象引用赋值

1. 写在前面
对象在JS中是一个引用类型,其中保存的是存储其属性的内存空间地址,与指针类似
将一个对象赋值给另一个对象其实是赋值了内存地址,此时这两个对象都可以通过保存的内存地址对内存数据进行更改,一个对象属性的更改就必然会引起另一个对象属性的变化
2. 例子1
bar.js :

//node中一个文件就是一个模块
const name= 'Harry';
let age = '18';
message = 'lulu lala';

function sayHello(){
    console.log('Hello' + name)
}
//在每一个模块里有一个全局对象exports
//默认是一个空对象,在内存中会开辟一个空间,exports实际保存的是存储其属性的内存地址,
//想把谁导出,就把谁作为exports的属性
exports.age = age;
exports.name = name;
exports.sayHello = sayHello();
//实际导出的其实是module.exports对象,node源码中进行了一步对象的引用赋值 module.exports = exports
module.exports.message = message;
setTimeout(()=>{
    console.log(exports.name) //hhhh
},2000)

main.js :

//这一步其实是将module.exports 对象赋值给了 bar对象
const bar = require('./bar')
console.log(bar.sayHello);//HelloHarry
console.log(bar.name);//Harry
console.log(bar.age);//18
console.log(bar.message);//lulu lala

setTimeout(()=>{
    bar.name = 'hhhh'
},1000)

上述代码其实等于如下图所示
在这里插入图片描述
module.exports 对象 exports对象 bar对象存储的都是同一个内存地址,所以一个对象属性的变化会引起另外两个的变化
这时候可能有人要问,既然最后导出的是module.exports,还要exports干嘛?
原因是在CommonJS规范内,强调要有一个exports导出的用法,有人学了CommonJS, 要是没有exports,他就会发现怎么exports在node里不能用了,这显然不可以。
为了验证最后导出的是module.exports我们来看例子2

3. 例子2
bar.js:

const name = 'Harry';
const age = '18';

exports.name = name;
exports.age = age;
module.exports = {message: 'hello'}

main.js :

const bar = require('./bar')
console.log(bar) //{message: 'hello'}

有人可能要问不是module.exports = exports 吗,因为这里module.exports被赋值了一个新的内存地址, 这时module.exports 和bar 里面的内存地址就和exports内的内存地址没关系了
也就是说现在的内存图是这样:
在这里插入图片描述
4. 例子3
再来个例子
main.js:

let bar = require('./bar');
setTimeout(()=>{
    bar = 'hhhh'
},1000)

bar.js:

module.exports = '123'

setTimeout(()=>{
    console.log(module.exports)//123
},2000)

这里为什么还是123呢?
因为JS中字符串是一个值类型,赋值时会把值的拷贝赋值,所以bar此时修改的只是值的拷贝,和原本值无关

5. 例子4
最后一个例子
main.js :

let bar = require('./bar');
setTimeout(()=>{
    bar.info.height = '1.70'
},1000)

bar.js :

const name = 'Harry';
const info = {
    height: '1.80'
}
module.exports.name = name;
module.exports.info = info;
setTimeout(()=>{
    console.log(module.exports.info.height)//1.70
},2000)

这个关系图就是这样
在这里插入图片描述
代码main.js中通过bar 的内存地址,获取到info的内存地址,修改了info的属性, 所以bar中的的info属性也得到修改

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值