js代码规范中文手册
以下引自 Node.js 官网:
Node.js® is a JavaScript runtime built on Chrome’s V8 JavaScript engine.
1. 新建一个 hello.js 并写入以下示例代码
const message = 'Hello Node.js!'
console.log(message)
2. 打开命令行并定位到 hello.js
文件所属目录
3. 在命令行中输入 node hello.js
回车执行
注意:
- 文件名不要起名为
node.js
- 文件名或者文件路径最好不要有中文
- 文件路径或者文件名不要出现空格
文件读取:
const fs = require('fs')
fs.readFile('/etc/passwd', (err, data) => {
if (err) throw err
console.log(data)
})
文件写入:
const fs = require('fs')
fs.writeFile('message.txt', 'Hello Node.js', (err) => {
if (err) throw err
console.log('The file has been saved!')
})
// 接下来,我们要干一件使用 Node 很有成就感的一件事儿
// 你可以使用 Node 非常轻松的构建一个 Web 服务器
// 在 Node 中专门提供了一个核心模块:http
// http 这个模块的职责就是帮你创建编写服务器的
// 1. 加载 http 核心模块
var http = require('http')
// 2. 使用 http.createServer() 方法创建一个 Web 服务器
// 返回一个 Server 实例
var server = http.createServer()
// 3. 服务器要干嘛?
// 提供服务:对 数据的服务
// 发请求
// 接收请求
// 处理请求
// 给个反馈(发送响应)
// 注册 request 请求事件
// 当客户端请求过来,就会自动触发服务器的 request 请求事件,然后执行第二个参数:回调处理函数
server.on('request', function () {
res.end('Hello Node.js!')
})
// 4. 绑定端口号,启动服务器
server.listen(3000, function () {
console.log('服务器启动成功,请求访问 http://127.0.0.1:3000/')
})
当你的网站开发越来越复杂代码越来越多的时候会经常遇到什么问题?
历史上,JavaScript一直没有模块(module)体系, 无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。 其他语言都有这项功能,比如Ruby的 require
、Python的 import
, 甚至就连CSS都有 @import
,但是JavaScript任何这方面的支持都没有,这对开发大型的、复杂的项目形成了巨大障碍。
现实角度(手机、电脑、活动板房):
- 生产效率高
- 可维护性好
程序角度(就是把大一个文件中很多的代码拆分到不同的小文件中,每个小文件就称之为一个模块,例如我们看到的 jQuery 真正的源码)
- 开发效率高(不需要在一个文件中翻来翻去,例如 jQuery 不可能在一个文件写 1w+ 代码,按照功能划分到不同文件中)
- 可维护性好(哪个功能出问题,直接定位该功能模块即可)
模块化的概念有了,那程序中的模块到底该具有哪些特性就满足我们的使用了呢?
下面我们具体来看一下在 Node.js 中如何在多模块之间进行输入与输出。
require
模块导入// 核心模块
var fs = require('fs')
// 第三方模块
// npm install marked
var marked = require('marked')
// 用户模块(自己写的),正确的,正确的方式
// 注意:加载自己写的模块,相对路径不能省略 ./
var foo = require('./foo.js')
// 用户模块(自己写的),正确的(推荐),可以省略后缀名 .js
var foo = require('./foo')
exports
模块导出导出多个成员:写法一(麻烦,不推荐):
// 导出多个成员:写法一
module.exports.a = 123
module.exports.b = 456
module.exports.c = 789
导出多个成员:写法二(推荐)
Node 为了降低开发人员的痛苦,所以为 module.exports
提供了一个别名 exports
(下面协大等价于上面的写法)。
console.log(exports === module.exports) // => true
exports.a = 123
exports.b = 456
exports.c = 789
exports.fn = function () {
}
导出多个成员:写法三(代码少可以,但是代码一多就不推荐了):
module.exports = {
d: 'hello',
e: 'world',
fn: function () {
fs.readFile(function () {
})
}
}
导出单个成员:(唯一的写法):
// 导出单个成员:错误的写法
// 因为每个模块最终导出是 module.exports 而不是 exports 这个别名
// exports = function (x, y) {
// return x + y
// }
// 导出单个成员:必须这么写
module.exports = function (x, y) {
return x + y
}
注意:导出单个只能导出一次,下面的情况后者会覆盖前者:
module.exports = 'hello'
// 以这个为准,后者会覆盖前者
module.exports = function (x, y) {
return x + y
}
exports = xxx
不行画图
exports 和 module.exports
的一个引用:
function fn() {
// 每个模块内部有一个 module 对象
// module 对象中有一个成员 exports 也是一个对象
var module = {
exports: {}
}
// 模块中同时还有一个成员 exports 等价于 module.exports
var exports = module.exports
console.log(exports === module.exports) // => true
// 这样是可以的,因为 exports === module.exports
// module.exports.a = 123
// exports.b = 456
// 这里重新赋值不管用,因为模块最后 return 的是 module.exports
// exports = function () {
// }
// 这才是正确的方式
module.exports = function () {
console.log(123)
}
// 最后导出的是 module.exports
return module.exports
}
var ret = fn()
console.log(ret)
moudle.exports.xxx = xxx
的方式moudle.exports.xxx = xxx
很麻烦,点儿的太多了exports
exports === module.exports
结果为 true
moudle.exports.xxx = xxx
的方式 完全可以:expots.xxx = xxx
module.exports = xxx
的方式exports = xxx
不管用return
的是 module.exportsexports
只是 module.exports
的一个引用exports = xx
重新赋值,也不会影响 module.exports
exports = module.exports
这个用来重新建立引用关系的exports = module.exports = function () {
console.log('默认函数被调用了')
}
exports.ajax = function () {
console.log('ajax 方法被调用了')
}
exports.get = function () {
console.log('get 方法被调用了')
}
在开始了解具体的规则之前,我们先来了解一下在 Node 中对不模块的一个具体分类,一共就三种类别:
mime
、art-template
、marked
参考文档:https://nodejs.org/dist/latest-v9.x/docs/api/
const fs = require('fs')
Node 中都以具名的方式提供了不同功能的模块,例如操作文件就是:fs
核心模块(系统模块)由 Node 提供,使用的时候都必须根据特定的核心模块名称来加载使用。例如使用文件操作模块:fs
var fs = require('fs')
// fs.readFile
// fs.writeFile
// fs.appendFile
模块名称 | 作用 |
---|---|
fs | 文件操作 |
http | 网络操作 |
path | 路径操作 |
url | url 地址操作 |
os | 操作系统信息 |
net | 一种更底层的网络操作方式 |
querystring | 解析查询字符串 |
util | 工具函数模块 |
… | … |
以 ./
或 ../
开头的模块标识就是文件模块,一般就是用户编写的。
一般就是通过 npm install
安装的模块就是第三方模块。
加载规则如下:
require('underscore')
underscore
目录,则找该目录下的 package.json
文件package.json
文件,则找该文件中的 main
属性,拿到 main 指定的入口模块node_modules
目录,规则同上。。。注意:对于第三方模块,我们都是 npm install
命令进行下载的,就放到项目根目录下的 node_modules
目录。
简而言之,如果require绝对路径的文件,查找时不会去遍历每一个node_modules目录,其速度最快。其余流程如下:
1 . 从module path数组中取出第一个目录作为查找基准。
2. 直接从目录中查找该文件,如果存在,则结束查找。如果不存在,则进行下一条查找。
3. 尝试添加.js、.json、.node后缀后查找,如果存在文件,则结束查找。如果不存在,则进行下一条。
4. 尝试将require的参数作为一个包来进行查找,读取目录下的package.json文件,取得main参数指定的文件。
5. 尝试查找该文件,如果存在,则结束查找。如果不存在,则进行第3条查找。
6. 如果继续失败,则取出module path数组中的下一个目录作为基准查找,循环第1至5个步骤。
7. 如果继续失败,循环第1至6个步骤,直到module path中的最后一个值。
8. 如果仍然失败,则抛出异常。
整个查找过程十分类似原型链的查找和作用域的查找。所幸Node.js对路径查找实现了缓存机制,否则由于每次判断路径都是同步阻塞式进行,会导致严重的性能消耗。
分享