Node.js基础——模块

在Vscode上使用node.js运行js代码

法一:终端运行

打开终端
在这里插入图片描述
在终端输入:node 文件路径\文件名
在这里插入图片描述

法二:右键Run Code

在这里插入图片描述
即可运行代码,得到结果:
在这里插入图片描述

Vsode设置node代码提示

打开vscode终端命令:

  1. 安装typings
npm install -g typings
  1. 安装nodejs的代码提示依赖
npm install @types/node

安装完成时候,输入代码就会有提示符了:
在这里插入图片描述

CommonJS规范——模块

JS标准的缺陷

  • JS是没有模块化系统(ES5)
    模块化:就是将一个大的代码分成若干个小的代码,没有模块化的代码都是不可复用的。
    JS有模块化,即一个js文件就可以看作是一个模块,但是如果模块2依赖于模块1那么必须先引入模块1,否则就会报错,所以说JS有模块但是没有模块化系统。
  • 标准库较少
    如jQuery就不是标准库,是由程序员自主开发的
  • 没有标准的接口
  • 缺乏管理系统

没有模块化系统带来的影响

  • 依赖关系
    如果按两个js文件之间有依赖关系,必须保证引入的顺序。
  • 命名空间的问题:
    当我们引入多个js文件,不同的js文件可能会有相同的变量名字,那么后引入的就会覆盖先引入的。
  • 代码组织
    在js中不能直接定义内部变量,不能起到保护作用。
    即两个js文件可以通过html直接访问对方文件的变量(需要以html做中介,在浏览器端输出):
    a.js:
function a (){
    
    
   console.log("我是a中的函数")
}

b.js:

b = 100
a()

text.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    <script type='text/javascript' src='./a.js'></script>
    <script type='text/javascript' src='b.js'></script>
    <script type='text/javascript'>
    </script>
</body>
</html>

浏览器输出:
在这里插入图片描述

但是,两个js文件之间不通过html直接运行是不可以直接访问的。
(都没有引入对方怎么可能看得见)
在这里插入图片描述

CommonJS的模块规范

CommonJS规范的提出,主要是为了弥补当前JavaScript没有标准的缺陷。
CommonJS规范对模块的定义十分简单∶

  • 模块定义:在Node中一个js文件就是一个模块
  • 模块引用:在Node中通过require()函数来引入外部的模块。
    引入之后才可以使用另一个js文件中的内容。
  • 模块标识:就是可以唯一表示一个模块的东西
    使用require()引入外部模块时,使用的路径就是模块标识

注意: commonJS只是一个规范,没有具体实现。由node进行实现:node根据规范编写相应的js代码。

node模块使用_CommomJS规范

默认情况一个js文件(即一个模块)里面的方法或者属性,外面是没法访问的。
如果要让外部可以访问模块里面的方法或者属性,就必须在模块里面通过exports或者module.exports暴露属性或者方法。
同时在另一个文件中使用require引入一个方法。

一个js文件里面的方法或者属性不可见的原因

在Node中,每一个js文件中的js代码都是独立运行在一个函数中,而不是全局作用域,所以一个模块的中使用var定义的的变量和函数在其他模块中无法访问。

(这里强调的是使用var,因为在JS中如果不使用var声明的变量就是全局变量,也就不受模块作用域的限制了;
但是生命成全局变量没有意义我们一般不这样用,想要设置成私有变量就用var,想要设置成全局变量就使用export进行暴露即可)

eg:hello.js:

console.log('hello world')
var x = 100
var y = 200

即hello.js:的代码我们可以看成是这样的:

(function (){
    
    
    console.log('hello world')
    var x = 100
    var y = 200
})()

所以无法直接访问另一个文件中访问var变量。

exports属性

需要将全局可见的变量暴露出去可以通过exports来进行设置:
只需要将需要暴露给外部的变量或方法设置为exports的属性即可。
eg:
暴露属性:

exports.x = 100
exports.y = 200

暴露方法:

exports.fn = function (){
    
    
    console.log('我是一个函数')
}

module.exports属性

需要将变量暴露出去也可以通过 module.exports来进行设置:
module.exports可以通过设置成属性,即.的形式暴露变量:
module.exports.XXX=XXX
也可以通过module.exports = {}暴露变量:

module.exports = {
    
    
    a,
    b,
    upper
}

require方法

require()可以传递一个文件的路径作为参数,node将会自动根据该路径来引入外部模块
如果使用相对路径,必须以.或..开头
eg:

require('./hello.js')

接收require返回值

  • require返回值
    使用require()引入模块以后,该函数会返回一个对象,这个对象代表的是引入的模块。
    所以我们设置变量接受这个对象,就可以接收引入模块传过来的变量了。
var md = require('./hello.js')

然后就可以通过 md.变量名 访问另一个文件向外暴露的对象

使用require引入例子

注意使用如果变量不使用exports声明,是无法将变量引入来的。

hello.js:

console.log('hello world')
exports.x = 100
exports.y = 200
exports.fn = function (){
    
    
    console.log('我是一个函数')
}

01.js:

var md = require('./hello.js')
console.log(md)
console.log(md.x)

输出:
在这里插入图片描述

路径的两种表示方式

模块分为核心模块和文件模块

  • 核心模块:由node引擎提供的模块
    核心模块的表示就是模块的名字,所以引入的时候直接写名字就可以了。
    eg:
var fs = require("fs")
  • 文件模块:由用户自己创建的模块
    文件模块的表示就是文件的路径(绝对路径,相对路径),引入的时候就将文件的位置写上。

注意: 如果引入的js文件有要执行的内容(如:调用了一个函数),使用require引入该文件的时候,就会执行对应的内容。

global

在node中有一个全局对象global,它的作用和网页中window类似
在全局中创建的变量都会作为global的属性保存
在全局中创建的函数都会作为global的方法保存

eg:

var a = 10
b = 100
console.log(global.a)
console.log(global.b)

输出:

undefined
100

js文件是运行在函数中的——验证

之前我们说一个js文件是运行在一个函数中的,我们来验证一下

  • 函数中才会有arguments参数
    在js文件按中输出arguments:
console.log(arguments)

输出:

[Arguments] {
    
    
  '0': {
    
     x: 100, y: 200, fn: [Function (anonymous)] },
  '1': [Function: require] {
    
    
    resolve: [Function: resolve] {
    
     paths: [Function: paths] },
    main: Module {
    
    
      id: '.',
      path: 'c:\\Users\\86198\\VScode\\qianDuan\\Node.js',
      exports: [Object],
      parent: null,
      filename: 'c:\\Users\\86198\\VScode\\qianDuan\\Node.js\\hello.js',
      loaded: false,
      children: [],
      paths: [Array]
    },
    extensions: [Object: null prototype] {
    
    
      '.js': [Function (anonymous)],
      '.json': [Function (anonymous)],
      '.node': [Function (anonymous)]
    },
    cache: [Object: null prototype] {
    
    
      'c:\\Users\\86198\\VScode\\qianDuan\\Node.js\\hello.js': [Module]
    }
  },
  '2': Module {
    
    
    id: '.',
    path: 'c:\\Users\\86198\\VScode\\qianDuan\\Node.js',
    exports: {
    
     x: 100, y: 200, fn: [Function (anonymous)] },
    parent: null,
    filename: 'c:\\Users\\86198\\VScode\\qianDuan\\Node.js\\hello.js',
    loaded: false,
    children: [],
    paths: [
      'c:\\Users\\86198\\VScode\\qianDuan\\Node.js\\node_modules',
      'c:\\Users\\86198\\VScode\\qianDuan\\node_modules',
      'c:\\Users\\86198\\VScode\\node_modules',
      'c:\\Users\\86198\\node_modules',
      'c:\\Users\\node_modules',
      'c:\\node_modules'
    ]
  },
  '3': 'c:\\Users\\86198\\VScode\\qianDuan\\Node.js\\hello.js',
  '4': 'c:\\Users\\86198\\VScode\\qianDuan\\Node.js'
}
  • agruments.callee属性保存的是当前执行的函数对象,可以进行输出查看

验证:

console.log(arguments.callee)

输出:

[Function (anonymous)]

验证:

console.log(arguments.callee+"")
// 拼串会调用toString方法,显示函数结构

输出:

function (exports, require, module, __filename, __dirname) {
    
    
console.log(arguments.callee + "")
// 拼串会调用toString方法,显示函数结构
}

结论:在node执行模块的时候,它会将我们写的内容嵌套在如下函数中:

function (exports, require, module, __filename, __dirname) {
    
    
     自己写的代码内容
}

我们直接使用的exports, require变量也是通过这个函数传过来的
参数解析:
- exports:该对象用来将变量或函数暴露到外部
- require:函数,用来引入外部的模块
- module:module代表的是当的模块本身,exports就是module的属性

console.log(module.exports == exports)

结果:True
- __filename:表示的是当前模块(js文件)的完整路径
- __dirname:表示的是当前模块所在文件夹的完整路径
eg:

console.log(__filename)
console.log(__dirname)

输出:

c:\Users\86198\VScode\qianDuan\Node.js\01module.js
c:\Users\86198\VScode\qianDuan\Node.js

exports和module.exports的区别

两者着本质上是一个对象,但是:

  • 通过exports只能使用.的方式来向外暴露内部变量
    exports.XXX=XXX
  • module.exports既可以通过.的形式,也可以直接赋值
    module.exports.XXX=XXX
    module.exports = {}

代码演示

示例一: 都可以使用.的方式来向外暴露内部变量
hello.js:

exports.name1 = '孙悟空'
module.exports.name2 = '猪八戒'

01.js:

var hello = require('./hello')
console.log(hello.name1)
console.log(hello.name2)

输出:

孙悟空
猪八戒

示例二: module.exports可以通过直接赋值暴露对象,而exports不可以
当给module.exports赋值的时候可以访问到:
hello.js

module.exports = {
    
    
    name2:'猪八戒'
} 

01.js:

var hello = require('./hello')
console.log(hello.name2)

输出:

猪八戒

当给exports赋值的时候可以不访问到:
hello.js

exports = {
    
    
    name2:'猪八戒'
} 

01.js

var hello = require('./hello')
console.log(hello.name2)

输出:

undefined

原理

原因其实很简单,变量指向的问题,实际上对外暴露是 module.exports 起的作用,而exports是因为指向它才具有暴露对象的能力。
如果给module.exports赋值,就是在里面定义向外暴露的对象;
而给exports赋值,exports就不指向module.exports,就无法定义向外暴露的对象了。

node模块的分类

node模块分成三类:node内置模块、自己写的模块、第三方模块
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/mantou_riji/article/details/124998052
今日推荐