node在vscode终端输入输出
//首先如果想在终端中输入参数,则需要开启全局对象process
const a = process.args[2]
const b = process.args[3]
console.log(a,b)
//num=1 num=2
//上面全局对象的变量index从2开始,第0项为node运行地址,第1项为所运行文件地址
$ node xx.js num=1,num=2
node程序传递参数
$ node xx.js args[0],args[1],...args[n] 直接追加在后面
console.log() 输出
consoel.clear() 清除控制台 cls
conole.tract() 打印函数调用栈
异常处理
当我们的代码输入不符合我们所要求的类型时,我们可以抛出错误来阻断代码执行
function (type){
if(type === 0)throw new Error() //如果type为0,则抛出错误
}
当抛出错误时,如果最近一层的对象不进行处理,则继续向层报错,上层捕获到错误后,如果不进行处理,则继续向上抛出错误,以此类推,直至到最顶层调用者,独断后续代码执行
function foo(){
throw new Error //抛出错误
}
function bar(){ //捕获错误但不进行处理,则继续向上抛出
foo()
}
function test(){ //捕获bar抛出的错误,不进行处理,继续向上抛出
bar()
}
test(); //最顶层调用者捕获test抛出的错误,阻断后续代码执行
当代码如果在抛出错误时需要执行一些必须的操作,则可以使用try{}catch(){},此时并不阻断后续代码的执行,仅当出现错误时执行对应的代码块
function foo(){
try{ //执行可能会发生错误的代码
throw new Error
}catch(err){ //捕获try中出现的错误,执行自身的代码,但并不阻断后续代码的执行
alert(err.message)
}
}
如果不论抛出或者捕获都要进行的代码块时,则可以使用finally来进行
function foo(){
try{
throw new Error
}catch(err){
console.log(err)
}finally{
console.log('不论如何,不影响我的执行')
}
}
模块化开发
-
最简单的导入导出方式
//第一个js文件 ex:why.js 该文件导出 const name = 'xi' const age = 20 const sum = (num1,num2)=>{ return num1+num2 } module.exports = { name, age, sum }
//第二个文件 导入 使用why.js的参数 const why = require('./why.js') console.log(why.name) console.log(why.age) console.log(why.sum(20,30))
当我们使用exports进行暴露时,我们暴露的是一个对象,此时对象指向我们所要暴露的变量,require是一个函数,它以我们所暴露出来的文件名进行查找,并返回所查找的对象,那次是第二个文件中的why在内存中也指向索要暴露出来的变量
//第一个文件 ex:why.js 该文件导出 const name = 'xi' const age = 20 const sum = (num1,num2)=>{ return num1+num2 } exports.name = name exports.age = age exports.sum = sum //当我们使用exports进行暴露时,依旧可以进行导出,但并不能直接导出一个对象 ex: exports = { name, age, sum } //此时并不会进行导出,主要是因为源码中的exports是指向moudule.exports module.exports = {} exports = module.exports //此时exports指向moudle.exports //也就是最终进行导出的依旧是moudle.exports
require查找规则
基本格式为
require(X)
-
如果X是一个 Node核心模块,比如
path
、http
、fs => file system
此时直接返回核心模块,并停止查找 -
如果X是以
./
or../
or/
根目录开头的-
首先将X作为一个文件在对应的目录下查找:
1.1 如果有后缀名,按照后缀名的格式查找对应的文件
1.2 如果没有后缀名,则会按照以下的顺序进行查找:
+ 直接查找文件X; + 查找X.js文件 + 查找X.json文件 + 查找X.node文件
-
如果没有找到对应的文件,则将X作为一个目录,查找目录下面的index文件
2.1 查找
X/index.js
文件2.2 查找
X/index.json
文件2.3 查找
X/index.node
文件
如果没有找到,则报错not found
-
-
如果X不是一个核心模块,且不是一个文件路径,则开始在文件的node_modules文件夹下找对应的index,如果没有找到,则向上层找,依次向上,如果找不到则not found
模块的加载过程
-
模块在被第一次引入时,模块中的js代码会被运行一次
-
模块被多次引入是,会缓存,最终只加载(运行)一次
每个js文件对应一个module的实例,每个模块对象module都有一个属性:loaded
为false标识还没有加载,为true便是已经加载
-
如果有循环引入,则按照程序的执行顺序进行加载
它是一种图结构,在遍历过程中先进行深度优先搜索(DepthFirstSearch),之后在进行广度优先搜索(BreathFirstSearch)
ES Moudle
平时使用我们必须使用
live server
来运行代码,因为modle并不支持file协议,支持http
、https
协议,所以当我们在本地运行代码时,此时的url 协议为file<-- 主要文件,引入主要模块文件 --> <script src='main.js'></script>
//主要js文件,引入次要模块文件 import {name,age,sum} from "./foo.js" //导入时也可以按照as给他们起别名 import {name as fname,age as fage,sum as fsum} from "./foo.js" //也可以将导出的所有内容放到一个标识符中 import * as foo from './foo.js'
//模块js文件 export const name = 'xi' export const age = 20 export const sum = (num1,num2)=>{ return num1+num2 } //第二种导出方式 const name = 'xi' const age = 20 const foo = function (){} export { //这里的export并非一个对象,里面存放的也是所有的变量标识符 name, age, foo } //第三种,也可以给他们起别名,使用as;当然此时我们导入时需要将对应导入文件的变量名修改为别名,使他们一一对应 export { name as fName, age as fAge, foo as fFoo }
当我们的js文件所使用的过多时,则可以将所有同文件下的js文件导入index.js,这样我们在主文件中只需要导入对应的index文件即可
//ex: index.js function foo(){} export {foo} from './math.js' //这样我们也可以直接将我们math文件导入index文件,并让index文件导出,使得主文件可以直接导入 //当我们文件中所有的的变量都需要被导入时,则直接使用通配符导出,此时对应文件的所有变量都可以导入该文件了 export * from './math.js'
当我们如果在导入时,不进行大括号,那则导入的时默认的导出;默认导出只有一个
function foo(){} //第一种,在export中使用别名 export { foo as default; } //第二种 直接使用export defalut export default foo; //此时将foo作为默认导出 import foo from "./math.js" //默认导入
import的使用,import函数返回的是一个Promise
我们如果有需要在js文件导入成功之前就需要执行的代码,那我们就需要进行异步操作;
使用
import("./").then
来进行异步操作import("./math.js").then(res=>console.log(res)) console.log('提前执行的代码') //此时的代码会再导入js之前就运行,不会等待js文件加载
ES11新增的特性
我们可以将import当作一个对
console.log(import.meta) //此时输出js文件所在的路径
-
ES Module
解析过程
一、 构建,根据地址找到对应的js文件,下载,之后浏览器对其解析(静态分析)为模块记录(数据结构)
二、 实例化,对模块记录进行实例化对象,并且分配内存空间,解析模块中的导入导出语句,把模块指向对应的内存地址; 仅解析import
和export
,其余代码会在运行时在进行解析
三、 运行,运行代码,计算值,赋值(将值填到对应的内存地址中)
在webpack环境中,我们可以将esmodule和commonjs互相引用
npm使用run和不使用run没有区别,他们是等价的;
package.json中常见的属性
-
name 项目名称 必须项,不支持中文
-
version 当前项目的版本号 必须项
-
description 描述信息,作为项目的基本描述
-
author 作者信息,个人/团队名 发布时用到
-
license 开源协议 发布时用到
-
private 决定当前项目是否私有,当为true时,npm无法发布,为了防止私有模块或者项目发布出去
-
main 程序的入口 所有导入文件的最终文件,如果其他人安装时,只需要在其中找到对应的一个文件即可,不需要一个个查找
-
scripts 常用于配置一些脚本命令,以键值对的形式存在,配置后我们可以使用
npm run
命令的key来执行这个命令 npm中常用的start
、test
、stop
、restart
是可以省略掉run的 -
dependencies 只当无论开发还是生成环境都需要依赖的包,我们在安装其他包时,可能此包也使用了一些其他包,此时我们想使用该包时,必须它的依赖包才可以
-
devDependencies 一些包在生产环境时不需要的,比如webpack、babel等;这个时候我们会通过
npm install webpack --sava-dev
来将他安装在devDependenices中,实际发布时并不会将该属性中的包发布出去 -
peerDependencies 这个属性中的是一种对等关系,有些的的使用基础是在另一个包基础上使用,那此时我们需要安装对应的基础包才可以正常使用,否则安装没有意义 比如:element-plus是依赖于vue3的,ant design是依赖于react、react-dom;只要在src中用到的,都需要放在生产环境中,我们使用的工具则基本放在dev环境中
-
semver版本规范
X主版本号(major):当做了不仅安荣的API修改,可能不兼容之前的版本
Y次版本号(minor):当做了向下兼容的功能性新功能,新功能增加,但是兼容之前的版本
Z版本号(patch):当作了向下兼容的问题修正,没有新功能,但是修复了之前的bug
^x.y.z
:标识X是保持布标的,y和z永远安装最新的版本~x.y.z
: 标识x和y保持不变的,z永远表示安装最新的版本
-
engines 用于指定Node和NPM的版本号;在安装过程中,会先寄哪查对应的引擎版本,如果不符合则报错;甚至我们可以指定所在的操作系统”ox”:[“darwin”,”linux],但是比较少用到
-
browserslist 用于配置打包后的js浏览器的兼容情况;一般是做浏览器的指定;例如当浏览器版本低于指定值时会将css或其他文件转换为对应的浏览器所支持的文件
npm install命令
-
全局安装
npm install xxx -g
此时我们在电脑的任何工具或文件中都可以使用;一般我们安装工具类,开发类不会安装在全局中 -
项目安装(局部安装)
npm install xxx
此时我们仅可以在该项目中使用 我们能也可以使用npm i xxx
来安装,这个命令是简写如果项目中存在package.json文件时,我们只需要使用
npm install
安装即可
安装过程
如果安装时出现最新版本高于lock版本,则会更新lock版本
npm uninstall xxx
卸载
npm rebuild
强制刷最新build
npm cache clean
清除缓存
set基本使用
在ES6之前,我们的存储结构主要有两种:数组、对象
Set类似于数组,但和数组最大的区别是元素不能重复
//数组
const arr = new Array(1,2,1) //[1,2,1]
//Set
const set = new Set(arr) //Set(2) { 1, 2 } Set数据可以使用展开运算符
//set添加数据
const set = new Set()
set.add(10)
console.log(set) //Set(2) { 10 }
const a = {}
const b = {}
set.add(a)
set.add(b)
console.log(set) //Set(2) { {},{}}
const c = {}
const d = c
set.add(c)
set.add(d)
console.log(set) //Set(1) { {} }
//个数
console.log(set.size) // 2
set.add(30) //添加
set.delete(30) //删除
set.has(20) //是否包含
set.clear() //清楚所有
set.forEach //遍历
for(const item of set){} //for-of遍历
WeakSet
- 只能存放对象类型
- 弱引用,如果没有其他引用该对象,则会被GC回收
- 无法遍历
const set = new Set()
let obj = {name:'xi'} //0x100
set.add(obj)
obj = null //此时0x100并不会被回收
const weakset = new WeakSet()
let obj2 = {name:'an'} //0x200
weakset.add(obj2)
obj2=null //此时0x200会被GC回收