文章目录
在Vscode上使用node.js运行js代码
法一:终端运行
打开终端
在终端输入:node 文件路径\文件名
法二:右键Run Code
即可运行代码,得到结果:
Vsode设置node代码提示
打开vscode终端命令:
- 安装typings
npm install -g typings
- 安装nodejs的代码提示依赖
npm install @types/node
安装完成时候,输入代码就会有提示符了:
CommonJS规范(模块化规范)
没有模块化系统带来的影响
-
引入方式
没有模块化之前js代码的引入方式是通过<script src="">
标签来引入到同一个html文件中。<script src="lib.js"></script> <!-- 第三方库 --> <script src="utils.js"></script> <script src="app.js"></script>
并且两个js之前是不恒互相引入的
-
依赖关系
如果按两个js文件之间有依赖关系,必须保证引入的顺序。如果文件A依赖于文件B,那么在引入时,就需要先引入文件B,再引入文件A。如果文件之间的依赖关系很复杂,这样的引入顺序就非常难以维护。 -
命名空间的问题:
当我们引入多个js文件,不同的js文件可能会有相同的变量名字,那么后引入的就会覆盖先引入的。即所有的js文件都是再全局空间进行定义的,每个js文件没有自己私有的命名空间。
eg:没有模块化的文件引入
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>
浏览器输出:
我是a中的函数
如果先引入b.js再引入a.js,就会报错
a未定义
使用模块化之后,就可以在b.js
文件中引入a.js
文件,避免了依赖引入的问题,同时可以确保依赖加载的顺序是先加载a.js
,再加载b.js
CommonJS的模块化规范
CommonJS规范的提出,主要是为了弥补当时JavaScript没有标准的缺陷(CommonJS提出的时候还没有ES6,当时是ES5吗,模块化的概念)。
CommonJS规范对模块的定义十分简单∶
- 模块定义:在Node中一个
js文件
就是一个模块 - 模块引用:在Node中通过
require()
函数来引入外部的模块。
引入之后才可以使用另一个js文件中的内容。 - 模块标识:就是可以唯一表示一个模块的东西
使用require()引入外部模块时,使用的路径就是模块标识
注意: commonJS只是一个规范,没有具体实现。由node进行实现:node根据规范编写相应的js代码。
node模块使用_CommomJS规范
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")
-
文件模块:由用户自己创建的模块
文件模块的表示就是文件的路径(绝对路径,相对路径),引入的时候就将文件的位置写上。var fs = require("./fs.js")
注意: 如果引入的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内置模块、自己写的模块、第三方模块