命名空间

所谓的命名空间说白了就是避免名字冲突.

假如全世界没有国家, 班级, 学校等概念. 有两个员工叫张三,老板喊了一句:张三过来扫厕所. 两个张三都会去扫厕所. 这就造成了冲突. 但如果一个张三是清华大学的, 另一个张三是北京大学的. 这时候老板喊: 北京大学那个张三过来扫厕所. 那么就不会造成混淆了.

编程语言的命名空间就是用来区分不同对象(万物皆对象,包括基础数据类型),这样就不会造成混淆.

闭包

很多语言都有包的概念进行命名空间的管理, 比如java,php等. 但js是没有包概念的. js实现命名空间管理是使用闭包的概念.

正常情况下,js只有全局变量和局部变量.全局变量全部绑定到终极对象window上面, 而局部变量在函数执行完成后会被销毁. 但如果我们让一个全局变量指向一个对象,window.$={}. 那么该对象就是命名空间, 里面的变量虽然是局部变量, 但是因为有全局变量引用,所以并不会被销毁.

下面例子 a,b,c变量都是直接绑定到window上面. 对于c变量,你可以调用c.b()而不会和b()冲突. 那是因为c变量指向的是一个封闭的对象. 这个对象就是一个命名空间.

window={}
var window.a='aaa'
var window.b=function(){return 'bbb'}
var window.c={a:'ccc',b:function(){return 'ddd'}}//重点注意

闭包只是命名空间的实现而已,没什么稀奇的.

下面例子 就是一个闭包, 先定义一个匿名函数, 再立马执行. 传入了window对象作为参数. 当执行完毕后, window对象就有了$属性, 并绑定了一个对象.

window = {};
(function(win){
    win.$={
        a:'ccc',
        b:function(){return 'ddd'}
    }
})(window)
console.log(window)
//{ '$': { a: 'ccc', b: [Function: b] } }

如果你导入一个对象并赋值给window对象的属性,不用闭包也是一样!

global

js有window全局对象,nodejs有global全局对象.

我们知道nodejs引入外部模块格式const hello=require('./hello'), 其实正真的格式是:

global = {}
const global.hello=require('./hello')

也就是说你导入的文件被global下的一个属性引用, 和js下的window引用属性无任何区别.

exports vs module.exports

重头戏来了,很多人搞不清楚exports和module.exports的区别,它们都可以用来导出模块.下面我们来分析过程.

  1. const path=require('path')这句话其实是调用global的require方法,根据路径找到文件,并把文件实例化一个对象绑定到global.path的属性下面.
//假如下面就是文件的对象,我们在对象里定义了三个方法a,b,c
{
    //global实例化该文件时把内部参数封装到module中,这个我们不用管.只需要知道有个exports={}属性
    let module={
        exports={}
    }
    let exports=module.exports
    //我们定义的函数
    function a(){return 'aaa'}
    function b(){return 'bbb'}
    function c(){return 'ccc'}
    //我们需要导出什么直接赋值
    module.exports.a=a
    module.exports.b=b
    exports.c=c
    //最终返回的就是它
    return module.exports
    //最后返回{a函数,b函数,c函数}
}

上面let exports=module.exports就是重点, 这也就是为什么我们通过添加属性的方式导出, module.exports和exports是等价的. 但是下面这种方式只有module.exports有效,exports是无效的.

{
    let module={
        exports={}
    }
    let exports=module.exports
    function a(){return 'aaa'}
    function b(){return 'bbb'}
    function c(){return 'ccc'}
    exports=a
    return module.exports
    //最后返回空对象{}
}

原因解析: 因为exports变量一开始指向module.exports, 但exports=c直接修改了exports变量的指向, 它不再指向于module.exports. 我们根本没有对module.exports做任何操作,所以最后返回的还是一个空对象, 并不是a函数.

结束语

看完这篇文章,相信大家对于exports和module.exports有了深入理解,可喜可贺可喜可贺

THE END
开启精彩搜索

历史搜索

用户名或邮箱
密码
用户名
密码
重复密码
邮箱
注册
找回密码
注册 登录
邮箱
邮箱验证码
发送验证码
59秒后可重发
新密码
重复密码
请选择支付方式
余额支付

购买将消耗【10

微信支付
微信扫码支付 0 元
[ 04分50秒 ]
请使用微信扫一扫
扫描二维码支付
支付宝支付
支付宝扫码支付 0 元
[ 04分50秒 ]
请使用支付宝扫一扫
扫描二维码支付
已完成支付
未完成支付

请输入验证码

点击验证码可以刷新

你确认吗?

确认

2024年10月1日

新增

新增