模块化

33 阅读3分钟

script 标签的两个参数, - async & defer

总结: 普通: - 解析到标签, 立刻pending, 并且下载同时执行 defer

  • 解析到标签, 开始异步下载, 继续往后进行完成之后开始执行

async

  • 解析到标签, 开始异步下载, 下载完成之后立刻执行且阻塞继续往后解析, 执行完成之后再继续向下

问题:

  • 污染全局作用域

模块化雏形 - IIFE

作用域的把控

定义函数 + 立即执行 => 独立空间

尝试定义一个简单的模块

    const module = (() => {
        let count = 0
        return {
            increase: () => ++count;
            reset: () => {
                count = 0 
             }
        }
    })()
    
    module.increase()
    module.reset()
    
    // 有外部依赖的情况下,如何优化处理
    const iifeModule = ((dependencyModule1, dependencyModule2) => {
        let count = 0
        return {
            increase: () => ++count;
            reset: () => {
                count = 0 
             }
        }
    })(dependencyModule1, dependencyModule2)
    
    // 掲示模式
     const iifeModule = ((dependencyModule1, dependencyModule2) => {
        let count = 0
        const increase =  () => ++count
        const reset = () => {
                count = 0 
             }
        return {
            increase,
            reset
        }
    })(dependencyModule1, dependencyModule2)

面试方向

    1. 深入模块化实现
    1. 转向框架,jquery vue react 模块化组件实现细节, 以及框架原理特征
    1. 转向设计模式, - 注重模块化设计

成熟期

CJS - commonsjs

node.js 制定的标准 特征

  • 通过module + export 去对外暴露接口
  • 通过require 去调用其他模块

模块的组织方式 dep.js

    // 引入部分
    const dependencyModule1 = require(../dependencyModule1)
    const dependencyModule2 = require(../dependencyModule1=2)
        let count = 0
        const increase =  () => ++count
        const reset = () => {
                count = 0 
             }
             
     // 暴露接口部分
     export.increase = increase
     export reset = reset
     
     module.exports = {
         increase,
         reset
     }
    const {increse, reset } = require('dep.js')
    increase()
    reset()

优点

  • CJS服务侧的角度解决了依赖全局污染的问题 + 完完全全地在写法上也实现了主观感受的模块化

缺点:

  • 针对服务端 => 异步

AMD

通过异步加载 + 允许定制回调函数

经典的实现框架: require.js

新增定义方式

    // 通过define来定义一个模块, 然后再用require去加载
    define(id, [depends], callback)
    require([module], callback)
    define('amdModule', ['dependencymodule1', 'dependencyModule2'], (dependencyModule1, dependencyModule2) => {
    
        let count = 0
        const increase =  () => ++count
        const reset = () => {
                count = 0 
         }
             
    })
    require(['amdModule'], amdModule => {
    
        amdModule.increase()
    })

** 面试题

    define('amdModule', [], require => {
        const dependencyModule1 = require(./dependencyModule1)
        const dependencyModule2 = require(./dependencyModule2)
    
    
    })

面试: 区分CJS和AMD? 手写兼容AMD& CJS的模块 // UMD

    define('amdModule', ['dependencymodule1', 'dependencyModule2'], (dependencyModule1, dependencyModule2) => {
    
        let count = 0
        const increase =  () => ++count
        const reset = () => {
                count = 0 
         }
             
    })(
    // 目标:一次去定位区分CJS和AMD
    // 1.CJS factory
    // 2. module module.export
    // define
    typeof module === 'Object'
    && module.exports
    && typeof define !== 'function'
    ? // 是CJS
     factory=> module.exports=> factory(require, exports, module)
     : // 是AMD
     define 
    )

优点:

  • 解决了服务 , 客户端异步动态依赖的问题

缺点:

  • 会有引入成本, 没有考虑按需加载

CMD规范

按需加载

主要应用框架 sea.js

    依赖就近
    define('moudle', (require, export, module) => {
        let $ = require('map')
        
        // 代码快

        if(xxx){
        
            return 
        }
        
        let depend2 = require(./dependencyModule2)
        // 代码快2
    })

优点:

  • 按需加载,依赖就近

缺点:

  • 依赖打包
  • 扩大模块内的体积

完全体 ESM

新增定义 引入: import 导出: export

    import dependencyModule1 from './dependencyModule1'
    
    // ...
    
    export default{
        increase, 
        reset
    }
    
    

面试:

    1. 处理动态一步依赖
    // es方式
    const moduleDependency = async() => {
        return await dependencyModule1.init()
    }
    
    // 原生
    import('./dependencyModule.js').then(dynamicEsmodule => {
        dynamicEsmodule.init()
    })

优点:

  • 通过最统一的形态整合了所有的js模块化

函数式编程

    const fetch = ajax(method, url, params)
    
    const fetch = ajax.get(url)
    
    const request = fetch(params)
    
    const fetch = ajax(method)(url)(params)
    
    send(request, fetch)
    
    // 科里化