Node.js梳理

简介

  1. 没有 BOM DOM
  2. 由 ECMAScript 和 服务端API 构成
  3. 不是语言,不是框架,是基于 Chrome的V8引擎 的 js 运行时环境
  4. npm 由 node 开发,npm 是开源包管理系统(快捷下载安装包)
  5. 没有全局作用域,只有模块作用域(文件),内部外部不能互相访问,好处是可以加载执行多个文件,可以完全避免变量命名冲突和污染
  6. 执行顺序按代码顺序
  7. 模块分3种
  • 核心模块require(‘fs’) os http path
  • 自定义文件模块 可省略后缀 相对路径一定加.//是根路径
  • 第三方模块

模块

什么是模块化?

  • 文件作用域
  • 通信规则
    • 加载
    • 导出

在 Node 中没有全局作用域的概念
在 Node 中,只能通过 require 方法来加载执行多个 JavaScript 脚本文件
require 加载只能是执行其中的代码,文件与文件之间由于是模块作用域,所以不会有污染的问题

  • 模块完全是封闭的
  • 外部无法访问内部
  • 内部也无法访问外部

模块作用域固然带来了一些好处,可以加载执行多个文件,可以完全避免变量命名冲突污染的问题
但是某些情况下,模块与模块是需要进行通信
在每个模块中,都提供了一个对象:exports
该对象默认是一个空对象
你要做的就是把需要被外部访问使用的成员手动的挂载到 exports 接口对象中
然后谁来 require 这个模块,谁就可以得到模块内部的 exports 接口对象

CommonJS与ES6

js使用require 和 import 引入依赖的区别?

require 和 import,都是为了JS模块化使用。

  1. require是Commonjs的语法,CommonJS的模块是对象,将要导出的对象,赋值给module这个对象的exports属性,输入时通过require这个方法来访问exports这个属性。
    import是ES6语法,ES6模块不是对象,而是通过export命令显示指定输出代码,定义了模块的对外接口后,再通过import加载模块。

  2. require整体加载模块(即加载fs所有方法),生成一个对象,这叫“运行时加载”,动态加载,因为只有运行时才能得到这个对象,不能在编译时做到静态化。
    import可以按需加载,编译时加载/静态加载,不能使用表达式和变量,即 ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高

module.exports={}   var xxx = require('./xxx.js')
export default {}  import xxx from './xxx.js'

commonjs模块与ES6模块的区别?

  1. commonjs输出的,是一个值的拷贝,而es6输出的是值的引用;

  2. commonjs是运行时加载/动态加载,es6是编译时输出接口/静态加载,效率更高;
    第二个差异是因为CommonJS加载的是一个对象(即module.exports属性),该对象只有在脚本运行结束时才会生成。而ES6模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。
    ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量

CommonJS:(用于node,同步加载)
  1. 对于基本数据类型,属于复制。即会被模块缓存。同时,在另一个模块可以对该模块输出的变量重新赋值。
  2. 对于复杂数据类型,属于浅拷贝。由于两个模块引用的对象指向同一个内存空间,因此对该模块的值做修改时会影响另一个模块。
  3. 当使用require命令加载某个模块时,就会运行整个模块的代码(运行时加载)。
  4. 当使用require命令加载同一个模块时,不会再执行该模块,而是取到缓存之中的值。也就是说,CommonJS模块无论加载多少次,都只会在第一次加载时运行一次,以后再加载,就返回第一次运行的结果,除非手动清除系统缓存。
  5. 循环加载时,属于加载时执行。即脚本代码在require的时候,就会全部执行。一旦出现某个模块被"循环加载",就只输出已经执行的部分,还未执行的部分不会输出。
ES6:不是动态解析,且依赖模块优先执行
  1. ES6模块中的值属于【动态只读引用】。

  2. 对于只读来说,即不允许重新赋值,import的变量是只读的,不论是基本数据类型还是复杂数据类型。当模块遇到import命令时,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。

  3. ES6模块不会缓存运行结果,而是动态地去被加载的模块取值动态引用原始值发生变化,import加载的值也会发生变化。不论是基本数据类型还是复杂数据类型。实时变化

  4. 循环加载时,ES6模块是动态引用。只要两个模块之间存在某个引用,代码就能够执行。

    export obj // 不添加大括号时会报错,因为我们要输出的是该对象的引用。注意是对该对象的引用,而不是拷贝。这也意味着在该模块改变name属性,会导致另一个模块下name属性的变化,这点与CommonJS不同,CommonJS只是对某个对象的拷贝

module.exports

// 在 Node 中,每个模块内部都有一个自己的 module 对象
// 该 module 对象中,有一个成员叫:exports 也是一个对象
// 也就是说如果你需要对外导出成员,只需要把导出的成员挂载到 module.exports 中
// 我们发现,每次导出接口成员的时候都通过 module.exports.xxx = xxx 的方式很麻烦,点儿的太多了
// 所以,Node 为了简化你的操作,专门提供了一个变量:exports 等于 module.exports
// 也就是说在模块中还有这么一句代码
// var exports = module.exports
// 给 exports 赋值会断开和 module.exports 之间的引用
// 同理,给 module.exports 重新赋值也会断开

//当一个模块需要导出单个成员的时候,这个时候必须使用:`module.exports = xxx` 的方式

path

const path = require('path')

join

  • path.join()方法使用平台特定的分隔符(windows: \反斜杠)把全部给定的 path 片段连接到一起,并规范化生成的路径。
    语法:
    path.join([path1], [path2], [...])
    
    说明:
    长度为零的 path 片段会被忽略。 如果连接后的路径字符串是一个长度为零的字符串,则返回 ‘.’,表示当前工作目录
    path.join()只会拼接给定的参数路径,不会再拼接当前的工作目录

resolve

  • path.resolve([from…],to)
    作用
    path.resolve方法把传入的路径或者路径段解析为绝对路径。
    语法:
path.resolve([from ...], to)

说明:
如果没有传入 path 片段,或者path 片段长度为零(空字符),则 path.resolve() 会返回当前工作目录的绝对路径(相当于使用path.resolve(__dirname))

__ dirname 和 __filename

是node自带的API

console.log(__dirname)  //相对该文件
fs.readFile(__dirname)  //都是相对该文件

直接写相对路径的话是: 相对于node命令
写dirname,filename才是相对于文件

  • __dirname 和 __filename
    • dirname: 动态的 获取当前文件所处目录的绝对路径
    • filename: 动态的 获取当前文件的绝对路径
    • 用来解决文件操作路径的相对路径问题,node在文件操作中使用相对路径不可靠
    • 因为在node的文件操作路径中,相对路径./a.txt 指的是相对于 终端执行 node 命令所处的目录,而不是当前文件所处目录,这样如果终端执行G:\html练习>node blog/app.js就会出错找不到路径
    • 所以为了尽量避免这个问题,都建议文件操作的相对路径都转为动态的绝对路径
    • 补充: 模块中的路径不受此影响,该怎么写还是怎么写,就是相对该文件
    • 方式:path.join(__dirname, '文件名')

例子

const http = require('http')
const fs = require('fs')
const server = http.createServer()
server.on('request',(req,res)=>{
	const url = req.url
	console.log('收到请求'+url)
	// response.write('hello')
	// response.write(' nodejs')
	// response.end()
	fs.readFile('./views/index.html',(err,data)=>{
		if(err){
			res.setHeader('Content-Type','text/plain;charset=utf-8')
			console.log('文件读取失败')
		}else{
			//data默认2进制,可以toString()
			//res.data支持2进制和字符串,所以不用处理
			res.setHeader('Content-Type','text/html;charset=utf-8')
			res.end(data)
		}
}).listen(3000,()=>{//一定是没被占用的端口
	console.log('服务器启动成功,可以通过 http://127.0.0.1:3000/ 访问')
})

附:content-type类型对应表 https://tool.oschina.net/commons
node学习笔记

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值