0%

前端基础

记录前端知识

JS

数组

arr.includes()

判断一个数组是否包含一个指定的值,如果是返回 true,否则false

1
2
arr.includes(searchElement)
arr.includes(searchElement, fromIndex)//fromIndex 从该索引处进行查找,如果为负值,则按升序从 array.length + fromIndex 的索引开始搜索
arr.slice()

slice() 方法可从已有的数组中返回选定的元素。

slice() 方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。

注意: slice() 方法不会改变原始数组

1
2
3
4
arr.slice()
arr.slice(start)
arr.slice(start, end)
//start和end是数组的索引(可为负数) 从第start开始截取到end(不包含)结束

字符串

str.lastIndexOf()

搜索该字符串并返回指定子字符串最后一次出现的索引,如果找到了 searchString,则返回最后一次出现的索引,否则返回 -1

1
2
str.lastIndexOf(searchString)
str.lastIndexOf(searchString, position)//返回指定子字符串在小于或等于 position 的位置中的最后一次出现的索引, 默认为 +Infinity
str.padStart()

用另一个字符串填充当前字符串(如果需要会重复填充),直到达到给定的长度。填充是从当前字符串的开头开始的。

1
2
3
4
5
6
padStart(targetLength)
padStart(targetLength, padString)
"abc".padStart(10); // " abc"
"abc".padStart(10, "foo"); // "foofoofabc"
"abc".padStart(6, "123465"); // "123abc"
"abc".padStart(1); // "abc"

Map对象

Map()
1
2
3
new Map()
new Map(iterable)//iterable是键值对数组或者其他可迭代对象,
//eg:const myMap = new Map([[1, "one"],[2, "two"],[3, "three"]]);

位运算符

判断n是否是2的整数次幂可以采用(n & (n - 1)) == 0

& AND 如果两位都是 1 则设置每位为 1
\ OR 如果两位之一为 1 则设置每位为 1
^ XOR 如果两位只有一位为 1 则设置每位为 1
~ NOT 反转所有位
<< 零填充左位移 通过从右推入零向左位移,并使最左边的位脱落。
>> 有符号右位移 通过从左推入最左位的拷贝来向右位移,并使最右边的位脱落。
>>> 零填充右位移 通过从左推入零来向右位移,并使最右边的位脱落。

Promise对象

Promise.resolve方法如果传入一个非Promise、非thenable的立即值,则得到的是以这个值填充的Promise,得到的不是相同的Promise

Promise.resolve方法如果传入一个真正的Promise,那么返回的就是这个Promise本身

获取Promise状态的方法
1
2
3
4
5
6
7
const promiseState = promise => {
const target = {}
return Promise.race([promise, target]).then(
value => (value === target) ? 'pending' : 'fulfilled',
() => 'rejected',
)
}

IntersectionObserver

异步观察目标元素与祖先元素或顶级文档视口的交叉状态的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
IntersectionObserver(callback[, options]) //构造函数
// callback 元素可见比例超过阈值,调用回调函数,参数如下:
// - entries 一个IntersectionObserverEntry对象的数组
// - observer 被调用的IntersectionObserver实例
// options 配置observer实例的对象,配置如下:
// - root 监听元素的祖先元素,其边界盒默认视口,默认文档视口
// - rootMargin 用于扩大或者缩小根的判定范围,默认值"0px 0px 0px 0px"
// - threshold 监听目标与边界盒交叉区域比例值判定可见,默认值0,采用阈值列表,使用升序排列,当任何阈值被越过,都会调用一次callback
IntersectionObserver.observe() // 开始监听目标元素
IntersectionObserver.disconnect() // 停止监听
IntersectionObserver.takeRecords() // 返回观察的所有IntersectionObserverEntry对象数组
IntersectionObserver.unobserve() // 停止监听目标元素

const intersectionObserver = new IntersectionObserver((entries) => {
if (entries[0].intersectionRatio <= 0) return;
loadItems(10);
console.log("Loaded new items");
});
intersectionObserver.observe(document.querySelector(".scrollerFooter"));

IntersectionObserverEntry

IntersectionObserverEntry 的实例作为 entries 参数被传递到一个IntersectionObserver的回调函数中;

1
2
3
4
5
6
7
8
// 属性
boundingClientRect // 目标元素边界信息
intersectionRatio // 返回IntersectionRect与boundingClientRect的比例
intersectionRect // 根与目标元素的相交区域
isIntersecting // 布尔值,判断目标元素与intersection observer的根是否相交
rootBounds // intersection observer的根
target // 与根出现相交区域改变的元素
time // 返回记录从IntersectionObserver的时间原点到交叉被触发时间的时间戳

CSS

text-transform
1
2
3
4
5
text-transform: none; // 阻止大小写被转换
text-transform: capitalize; // 单词首字母大写
text-transform: uppercase; // 全部大写
text-transform: lowercase; // 全部小写
text-transform: full-width; // 强制将字符写在正方形内,实现与中文对齐 firefox || safari

DOM/BOM

screenX:参照电脑屏幕左上角,鼠标点击位置相对于电脑屏幕左上角的水平偏移量

clientX:参照浏览器内容区域左上角,鼠标点击位置相对于浏览器可视区域的水平偏移量

pageX:参照网页的左上角,clientX加上水平滚动条的距离

offsetX:鼠标点击位置相对于触发事件对象的水平距离

WebAPI

Performance

获取当前页面与性能相关的信息

调试技巧

vscode中三层以上的对象无法在控制台输出,采用console.dir(obj, { depth: null });的格式输出即可

命名规范

组件:大驼峰

文件夹:小写单词并用-连接

js文件:小写单词并用-连接(类文件:大驼峰)

变量:小驼峰 类型+对象描述

函数:小驼峰 (构造函数:大驼峰)前缀使用动词描述

常量:大写

私有属性:_前缀加公共属性/函数的命名方式

算法

动态规划通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。适用于有重叠子问题和最优子结构性质的问题,并且记录所有子问题的结果。动态规划有自底向上和自顶向下两种解决问题的方式。自顶向下即记忆化递归,自底向上就是递推。一旦一个子问题的求解得到结果,以后的计算过程就不会修改它,这样的特点叫做无后效性,求解问题的过程形成了一张有向无环图。

bfs中每一层要用新的变量保存

位运算技巧

计算二进制中1的位数:

1
const countOnes = (n) => n.toString(2).split("1")

计算机网络

  1. TCP与UDP区别:
    • TCP面向连接、可靠,UDP无连接协议不可靠
    • TCP面向字节流,UDP面向报文
    • TCP支持点对点通信,UDP支持一对一,一对多,多对一,多对多
    • TCP首部开销比UDP大
  2. 输入URL到获得页面经历了什么
    • 查询DNS,获取域名对应的IP。首先查询本地hosts文件的ip映射关系,查询本地DNS解析器缓存,查询本地DNS服务器,查询根DNS服务器,查询域服务器
    • 获取到IP后,浏览器随机端口向服务器的80端口发起TCP请求,向服务器发起三次握手
    • 建立安全的加密信道后,发送HTTP请求
    • 服务器处理请求,返回资源文件
    • 关闭TCP连接,浏览器解析渲染,构建DOM树,构建Render树,布局Render树,绘制Render树

Typescript

双竖杠与双问号的区别:双竖杠||,只要前面的值转为布尔值为false时,就取后面,否则取前面,如undefined、null、false、空字符串和数值0

而双问号则为:前面的值为null、undefined,则取后面的值,否则都取前面的值。

Typescript中类型别名和接口的区别

1)用途不同
类型别名(Type Aliases)可以用于定义原始类型、联合类型、元组以及复杂对象等各种类型。接口(Interfaces)则主要用于定义对象类型。

2)扩展方式不同
接口可以通过extends关键字进行扩展,而类型别名则需要使用交叉类型 & 来进行组合。

3)合并机制不同
接口支持声明合并,即可以多次声明同一个接口名称,它们会自动合并。而类型别名不支持这一点,重复声明同名的别名会导致编译错误。

其他

Storybook

storybook的doc中类型不显示

组件tsx文件中ts类型要写在传参后面,eg:

1
2
3
4
5
6
7
8
export const Button = ({
primary = false,
size = 'medium',
backgroundColor,
label,
hoverOpacity = 0.8,
...props
}: ButtonProps) => {...
storybook在vercel下部署配置vercel.json

指定build的指令和文件输出的目录

1
2
3
4
5
6
7
8
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"buildCommand": "npm run build-storybook",
"devCommand": "npm run storybook",
"installCommand": "npm install",
"framework": null,
"outputDirectory": "./storybook-static"
}

Bug

input标签输入中文的拼音时候会触发onChange事件,中断拼音输入

input中文输入的时候会重复触发onChange并且赋值value,无法完成中文输入。需要采用compositionEvent控制输入法触发与结束。

onCompositionStart 事件在用户开始使用输入法输入时触发。

onCompositionEnd 事件在用户完成使用输入法输入时触发。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const [isComposing, setIsComposing] = useState(false);
const inputRef = useRef<HTMLInputElement | null>(null);

useEffect(() => {
if (inputRef.current) {
inputRef.current.value = value ?? defaultValue ?? "";
}
}, [value, defaultValue]);

const handleCompositionStart = () => {
setIsComposing(true);
};

const handleCompositionEnd = (
event: React.CompositionEvent<HTMLInputElement>
) => {
setIsComposing(false);
if (onChange) {
onChange(event as any);
}
};

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (!isComposing && onChange) {
onChange(event);
}
};