2024年最新随笔-JS早期模块化的实现与缺点分析,一起看看这些大厂面试真题查漏补缺吧

读者福利

========

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

由于篇幅过长,就不展示所有面试题了,想要完整面试题目的朋友(另有小编自己整理的2024大厂高频面试题及答案附赠)


此时,JS模块的一个重要特性展现出来:低耦合

即每个JS模块都只完成特定功能,而不是完成所有功能,我们在设计JS模块时,尽量往粒度小的方向设计,便于后期复用和整改。

但是此时又出现了新问题,比如引入的js出现了重复的变量定义,会发生覆盖,以及污染全局变量

// common1.js

var a = 1

// a.js

var a = 2

// a.html

这些问题的原因就是,通过script标签引入的js文件中代码,相当于在全局作用域下,所以每个JS文件中定义在顶层的变量都会变成全局变量,即污染了全局变量

为了解决这个问题,只能为每个JS模块定义一个单独的作用域,让JS模块内部变量不会影响全局变量,所以自然而然想到了函数,因为ES6之前除了全局作用域就是函数作用域。

这里的函数有两种选择:

1、普通函数

2、立即执行函数

而我们一般会选择立即执行函数,因为普通函数还需要一行调用代码,这样才能保证在script标签引入JS模块后,执行JS模块中代码,对应的普通函数才能执行。而立即执行函数会在script标签引入JS模块后立即执行。

// common1.js

(function(){

var a = 1

})()

// a.js

(function(){

var a = 2

})()

// a.html

这就解决了JS模块变量污染全局的问题,且又提出了一个模块的重要特性:

模块需要具备自身的模块作用域,即高内聚,或者说封装性。模块内部设计不对外开放。

而说到封装性,自然而然又想到了getter和setter,即模块不能自己玩自己的,它需要和外部交流,它需要提供入口接收外部信息,需要提供出口反馈处理结果

当这个实现不难,因为现在JS模块当前是一个立即执行函数,函数的特点就是可以接收外部参数,可以返回值

// common1.js

var moduleC = (function(window){

var a = 1

return {a}

})(window)

// a.js

var moduleA = (function(window){

var a = 2

return {a}

})(window)

以上就是一种实现方案,即立即执行函数接收window,返回一个对象

我们需要思考的是,为什么需要接收window,如果不接受window的话,立即执行函数内部可以拿到window吗?

当然可以,我们知道被script标签引入的JS代码,都处于全局作用域下,所以此时立即执行函数也相当于在全局作用域下,如果立即执行函数内部需要window,则可以沿着作用域链找到全局作用域拿到window,但是这样比较浪费性能。

最好地方式就是在全局作用域下调用立即执行函数时传入window作为立即执行函数的参数,这样的效率要比沿着作用域链查找快。

其次我们需要思考的是,为什么立即执行函数返回的是一个对象,而不是变量本身?

这其实取决于你的模块到底需要返回什么,如果你的模块返回值确实只是单个变量,则return a没有问题,但是大部分情况下,模块返回都不是一个简单的变量,可能是多个变量,或多个变量和函数以及对象,以及模块后期拓展功能,相应的返回值也需要拓展,而对象的拓展性要比变量和函数好的多,所以绝大数情况下,我们将一个对象作为模块的返回值。

最后,我们思考下,将模块的返回值赋值给一个全局变量,会不会造成全局变量污染?

会,但是这是没有办法的,因为模块对外暴露时,总要有个载体,且能被外部访问到,所以只能将模块返回值定义到一个全局变量上,此时我们只能尽量避免在全局代码中使用模块对外暴露的变量,另一方面,我们对于模块暴露的变量命名需要尽可能的特殊化,不要使用常规变量名,最著名的例子就是jQuery的$符号

以上完成了模块的输入输出定义,那么模块的输入是否可以是另一个模块呢?

答案是可能的,因为模块之间的依赖的很普遍的行为,比如模块a 依赖于模块b,模块b 依赖于 模块c,所以必须要先产生c模块,才能产生b模块,最后才能产生a模块

所以模块之间想要依赖,则必须要先产生模块。

而浏览器端,JS模块产生,只有一个途径,script标签导入JS文件,所以模块的依赖和script标签导入JS文件的顺序形成了强关联。

上面引入顺序一旦发生改变,则会报错,比如

在script引入a.js时就会报错,找不到b(b.js的输出)

以上示例,说明一个问题:模块之间的依赖,无法写在模块中,只能在一个HTML文件的script标签实现。

这就导致了一个致命的问题:

一旦HTML文件引入了较多的JS文件,你将无法从中显示地识别出模块之间依赖关系,只能依靠自身经验来发现依赖关系,且非常容易通过变更script引入js文件地顺序导致模块依赖报错。

结束

一次完整的面试流程就是这样啦,小编综合了腾讯的面试题做了一份前端面试题PDF文档,里面有面试题的详细解析,分享给小伙伴们,有没有需要的小伙伴们都去领取!

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值