之前都懒得加更新列表,现在补一下(以前的也记不得了,从这次开始)
- 2024/3/24 数据处理统合在一起,添加不满补零的部分
目录
delete
我在看nodejs的808协议解析的代码的时候看到了delete这个操作用来对超时做处理。
因为js自带垃圾回收机制,所以delete不常用
但是比如前端通过接口向后端发一个对象,比如这个对象是form表单里的数据,如果不要把每个参数都传给后端,可以用delete删除掉某几个字段;
var obj = {name: "John", age: 25};
delete obj.age;
console.log(obj); // 输出: {name: "John"}
__dirname和__filename
__dirname:用来动态获取当前文件模块所属目录的绝对路径
__filename:用来动态获取当前文件的绝对路径
Import、Require、interopRequireDefault
require
require是CommonJS的规范
require是一开始就执行读取模块;
(Nodejs使用的是require)
静态编译:
引用了之后会放入缓存,所以可以使用require(‘…’).xxx直接使用里面的属性,无需再次读取
import
import是ES6的规范,
import是先不执行,遇到使用到的时候再真正的读取模块;
interopRequireDefault
interopRequireDefault的作用就是判断require的模块是否是已经被babel编译过的模块,如果是,则当前require的引用一定存在一个default属性;否则为他加一个default属性,这样便不会调用模块的default为undefined的情况了。
参考:https://www.dvy.com.cn/2020/12/06/6976.html
引用出现的一些问题
循环引用
多个文件引用的时候一定要避免循环引用,无论是几个文件循环都会导致报错,在一开始写代码的时候就要注意将工具函数分出来!
引用文件的变量作用域
举个例子,如下
// utils.js
let a = 1;
const fun = () => {
a = 2;
};
const getA = () => {
console.log(a);
};
let obj = {
x: 0,
};
const changeObj = () => {
obj.x = 1;
console.log(obj);
};
module.exports = { a, fun, getA, obj, changeObj };
// main.js
const utils = require("./utils/utils");
utils.fun();
console.log(utils.a); // 1
utils.getA(); // 2
utils.a = 3;
utils.getA(); // 2
// console.log(utils.obj); // { x: 0 }
utils.changeObj(); // { x: 1 }
console.log(utils.obj); // { x: 1 }
utils.obj.x = 2;
console.log(utils.obj); // { x: 2 }
可以看出以下两点,
1.js的执行逻辑是一个文件一旦被加载就不会被销毁,直到进程结束才会被销毁
2.引用可以当成浅拷贝,被赋值的时候如果是对象之类的引用数据类型,那么只会获得一个指针地址,而不是整个数据。
引入导致的路径错误问题
// main.js
let readF = require("./utils/readFile");
readF();
// readFile.js
const fs = require("fs");
const readF = () => {
let content = fs.readFileSync("./file.txt");
console.log(content);
};
module.exports = readF;
如上情况会报错Error: ENOENT: no such file or directory, open './file.txt'
因为引用这个模块的时候这个路径只是个字符串,会直接引用到main.js中,也就是在main.js中使用相对路径。所以需要用__dirname变成绝对路径。
// readFile.js
const fs = require("fs");
const readF = () => {
let content = fs.readFileSync(__dirname+"/file.txt");
console.log(content);
};
module.exports = readF;
defer和async
之前面试准备的时候知道这两个东西,就是你用script标签的时候可以使用这两个不对html页面渲染阻塞
执行顺序:
普通script:遇到先网络加载,再执行脚本,再继续渲染
defer:遇到并行下载,等渲染完了再执行
async:遇到并行下载,下载完了直接执行
严格模式
“use strict”
防止不规范导致安全问题
undefined和null
!undefined和!null结果都是true
数据处理
将版权符号变回原始字符串
String.raw`\u00A9` // 将版权符号变回字符串
循环将字符串数组转为数字数组
看似要几步的问题可以一步解决
let numArr = strArr.map(Number);
不满补零
// 1. 字符串直接调用方法
str.padStart(n, '0') // 补满到n位数
// 2. 数字前面加0然后取后n位
('0' + time.getMonth()+1).slice(-n)
parseInt等转数字的方法
如果参数是数字加字符,会自动过滤字符,如果字符在前是NaN,数字在前会过滤后面的字符,示例如下:
let str1 = "16aaa";
let str2 = "aaa16";
let str3 = "12a12";
console.log(parseInt(str1)); // 16
console.log(parseInt(str2)); // NaN
console.log(parseInt(str3)); // 12
标签语句
之前好像见过但是没怎么在意,看红宝书的时候刚好看到了,记录一下,这个在多层循环的时候可以任意跳出某个循环,可以用continue和break加上label名称,如下示例
let i,
j,
count = 0;
label1: for (i = 0; i < 10; i++) {
label2: for (j = 0; j < 10; j++) {
if (i > 5) {
break label1;
}
if (j > 5) {
break label2;
}
count++;
}
}
console.log(i, j, count); // 6 0 36
关于文件执行流程
nodejs会逐个编译每个被引用的模块,也就是说,只要有一个文件有一个可以直接执行的函数且这个文件被引用了,就会直接执行
日志打印问题
console.log(“xxx:”+obj)
如果用这种表达obj就会打印成[object][object]
console.log(“xxx:”,obj)
这样就可以完整打印出来obj的结构
闭包
看了阮一峰的古早时期的博客,有一篇讲了闭包,里面说
它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
我对此的理解是当闭包了之后return出来的函数就变成了全局变量,不走垃圾回收,而且它所依赖的也就是闭包他的那个函数里面的东西也变成了全局变量可供调用
undefined和void 0
之前搞视频解码的时候用了wfs,看到源码里有个var mimeType = void 0;
领导问我这是干什么的,我说这是给mimeType赋值undefined的,但是我又想了想,为什么不直接用undefined呢,去搜了下,发现这个undefined竟然可以不是关键字,可以作为变量使用!存在即合理,这是我最近尤其能感受到的道理!
let undefined = 1;
let x = undefined;
console.log(x); // 1
map相关
map变对象
写了nodejs之后发现map使用的越来越多,比如需要循环查询数据库,为了提高效率,就可以一次性全查出来,放在map里方便快速查询,经典的用空间换时间的做法;
但是也有的情况是我做了map,且又要把map返回给前端,但是传map格式是不行的,只能传object,那么就可以用如下方法直接转换成object
Object.fromEntries(map)
用类似map的格式代替多重if
工作需求中,我想写一个评分,如果分数高于90设为1类,高于80设为2类,以此类推;switch只能用等于判断,用不了,有五种情况,要五个if判断看起来有很捞,没办法,求助聪明的gpt得到以下结果:
const levelMapping = {
1: 90,
2: 80,
3: 70,
4: 60
}
const getLevel = result => {
for (const [level, threshold] of Object.entries(levelMapping)) {
if (result >= threshold) {
return level
}
}
return 5 // 默认返回 5
}