Node-模块化开发

1. 什么是模块化开发

1.1 什么是模块化开发

  1. 事实上模块化开发最终的目的是将程序划分成一个个小的结构
  2. 这个结构中编写属于自己的逻辑代码,有自己的作用域,不会影响到其他的结构
  3. 这个结构可以将自己希望暴露的变量、函数、对象等导出给其结构使用
  4. 也可以通过某种方式,导入另外结构中的变量、函数、对象等
  5. 上面说提到的结构,就是模块,按照这种结构划分开发程序的过程,就是模块化开发的过程

1.2 JavaScript 设计缺陷

  1. 比如var定义的变量作用域问题
  2. 比如JavaScript的面向对象并不能像常规面向对象语言一样使用class
  3. 比如JavaScript没有模块化的问题
  4. Brendan Eich本人也多次承认过JavaScript设计之初的缺陷,但是随着JavaScript的发展以及标准化,存在的缺陷问题基本都得到了完善
  5. ES6(2015)推出了自己的模块化方案
  6. 在此之前,为了让JavaScript支持模块化,涌现出了很多不同的模块化规范:AMDCMDCommonJS

1.3 没有模块化的问题

  1. 我们假设有两个人:小明和小丽同时在开发一个项目,并且会将自己的JavaScript代码放在一个单独的js文件中
  2. 小明开发了aaa.js文件,代码如下:
    var flag = true
    
    if (flag) {
    	console.log("aaa的flag为true")
    }
    
  3. 小丽开发了bbb.js文件,代码如下:
    var flag = false
    
    if (!flag) {
    	console.log("bbb使用了flag为false")
    }
    
  4. 很明显出现了一个问题:大家都喜欢使用flag来存储一个boolean类型的值,但是一个人赋值了true,一个人赋值了false,如果之后都不再使用,那么也没有关系,但是,小明又开发了ccc.js文件
    if (flag) {
    	console.log("使用了aaa的flag")
    }
    // 小明发现ccc中的flag值不对,因为是小丽将flag赋值为了false,
    
  5. 没有模块化对于一个大型项目来说是灾难性的

2. CommonJS规范

2.1 CommonJSNode

  1. 我们需要知道CommonJS是一个规范,最初提出来是在浏览器以外的地方使用,并且当时被命名为ServerJS,后来为了体现它的广泛性,修改为CommonJS,平时我们也会简称为CJS
    a. NodeCommonJS在服务器端一个具有代表性的实现
    b. BrowserifyCommonJS在浏览器中的一种实现
    c. webpack打包工具具备对CommonJS的支持和转换
  2. 所以,Node中对CommonJS进行了支持和实现,让我们在开发node的过程中可以方便的进行模块化开发
    a. 在Node中每一个js文件都是一个单独的模块
    b. 这个模块中包括CommonJS规范的核心变量:exportsmodule.exportsrequire
    c. 我们可以使用这些变量来方便的进行模块化开发
  3. 前面我们提到过模块化的核心是导出和导入,Node中对其进行了实现:
    a. exportsmodule.exports可以负责对模块中的内容进行导出
    b. require函数可以帮助我们导入其他模块(自定义模块、系统模块、第三方库模块)中的内容

2.2 Node模块化开发

  1. node中每一个文件都是一个独立的模块,有自己的作用域
  2. 那么,就意味着别的模块中不能随便访问另外一个模块中的内容
  3. 模块需要导出自己想要暴露的变量、函数、对象等等
  4. 另一个模块就可以导入自己想要使用的变量、函数、对象等等

2.3 exports导出

  1. exports是一个对象,我们可以在这个对象中添加很多个属性,添加的属性会导出
    // a.js 模块导出
    exports.name = name
    exports.age = age
    exports.sayHello = sayHello  // syaHolle是函数
    
    // b.js 导入
    const bar = require('./bar')
    console.log(bar.name)
    console.log(bar.age)
    console.log(bar.sayHolle())
    

2.4 module.exports导出

  1. Node中我们经常导出东西的时候,是通过module.exports导出的
    module.exports = 'hello'
    // 或者
    module.exports = function () {}
    
  2. 一个模块中只能有一个module.exports

2.5 module.exports导出

  1. 模块成员导出的另一种方式:module.exports
    a. module.exports导出和exports完全一样,它们之间只是名称不一样,
    b. exportsmodule.exports的别名(地址引用关系,指向同一内存地址)
    c. 当它们指向不同地址的时候,导出对象最终以module.exports为准
    d. 比如一个模块要导出的是某个成员,而非对象,这时候只能改变module.exports的指向才有效

2.6 module.exportsexports的关系

  1. 在 Node 中,每个模块内部都有一个自己的 module 对象

  2. module 对象中,有一个成员叫 exports 也是一个对象

  3. 因为每次导出成员需要 module.exports.xxx = xxx 比较麻烦

  4. 所以为了简化,它的内部,做了这样的操作 exports = module.exports

  5. exports 等价于 module.exports 它们指向了同一个内存地址

  6. 由于 require 方法中返回的是 module.exports 对象,所以当返回导出单个成员的时候:
    require = 'hah' 它改变了指向,跟module.exports没有关系
    module.exports = 'hah' 而它改变指向,导出的就是改变指向后的它

2.7 require导入

  1. require 有两个作用: 执行加载模块中的代码得到被加载模块中的exports导出接口对象

    // 例如:b.js 文件导出的对象,导入到 a.js 文件中
     let a = require('./b.js')
     // require 加载并执行了 b.js 文件模块,返回被加载模块中 exports 导出的接口对象 
     a.num
     a.sayHi
     // 然后利用 a 对象就可以访问, b.js 模块中导出对象的属性了
     // 注:导入模块,在当前文件夹下路径必须以./开头,后缀可以省略
    
  2. 优先从缓存加载: require 加载页面的时候,会把加载的页面先缓存起来,后面再有 require 加载同一个页面会先去缓存中查找,如果有就从缓存拿,从缓存拿就意味着不会从新加载页面,页面也就不会重复执行,而是直接获取到加载的对象,这样做的目的是避免重复加载,提高模块加载的效率

  3. require(参数) 加载的参数分为三种:模块标识路径形式的模块
    a. 模块标识加载的为:核心模块
    b. 路径形式模块加载的为:自己写的模块,自己写的模块./或者../不能省略,后缀可以省略,/(根目录)
    c. 包名加载的是:第三方模块

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值