虽然 nodejs 也是用了 JS 标准的语法(以及 ES6 的语法规范),但是肯定有一些地方和前端 JS 不一样。因此这里简单的总结一下,只说重点,不再从头说起。
- 和浏览器 JS 的不同
- 模块化
- 异步
前端说的 JS ,即浏览器端运行的 JS 其实是两个标准的合并。只有这俩合起来,在实际开发中才能使用,否则:例如只讲第一个标准的话,那只能写 demo 演示一下,没法实际用。
- ECMA 262 标准 —— 即 JS 的基本语法,如何定义变量、变量类型、原型、作用域、异步等
- W3C 的 Web-API 标准 —— 包括 BOM DOM 操作、ajax 、存储等
而在 nodejs 中,第一个标准,即 ECMA 262 标准继续使用,也就是 JS 基本语法继续使用,JS 原型、异步、闭包等特性也继续保持。但是第二个标准就没法继续使用过了,例如window
document
location
getElementById
等,这些就都没有了,因为 nodejs 是 server 端的,根本没有浏览器的那些特性。但是 nodejs 中定义了自己在 server 端特有的 API,例如http
fs
Stream
os
等,这些都是 server 端才有的特性。
总结一下,就两点
- 继续使用 ECMA 262 标准,即 JS 的基本语法
- 定义了 server 端特性的 API ,如
http
fs
等
nodejs 使用 CommonJS 模块化规范,其中会用到require
module.exports
关键字。归总一下,一共有三种引用场景:
比较简单,即引用 nodejs 默认提供的核心 API 。例如:
var http = require('http')
var fs = require('fs')
var os = require('os')
npm 安装第三发模块时,可通过加入--save
或--save-dev
,这样安装之后模块名称会保存在package.json
中。然后即可根据模块名称引用刚刚安装的模块,常见的有:
var lodash = require('lodash')
var React = require('react')
var webpack = require('webpack')
以上require
的时候都是输入名称,也可以输入相对路径来引用自己定义的模块。自己新建一个文件a.js
,内容为
module.exports = function (info) {
console.log(info)
}
然后新建一个文件b.js
(和a.js
同目录),内容为
var a = require('./a.js') // 引用自定义模块 a.js
a('hello world')
node b.js
,即可看到效果。
这里有一个问题,按照 JS 语法来说,以上代码中 require
module.exports
都是未定义的变量,应该会报错的。其实,在编译过程中,nodejs 会获取这段代码,然后进行一个函数封装,然后变成这样,问题就解决了。
// 上面提出的未定义的变量,都是函数的参数,是执行时被传入的
// 同理的还是 __filename, __dirname
(function (exports, require, module, __filename, __dirname) {
var fs = requre('fs')
module.exports = function () {
console.log(__dirname)
console.log(__filename)
}
})
这就算是一个意外收获了,不过遇到问题还是要多考虑一下原型。
这里提出“异步”,并不是要讲什么新内容,而是着重提示:接下来的讲解,会用到很多异步的知识,因此异步必须要掌握全面。提醒一下,还不了解的同学尽快去补充学习:
- 异步和同步的区别
- 异步和单线程
- event loop
- callback 方式
- Promise
- async/await
可阅读作者写的 深入理解 JS 异步