基础扎实了,框架便是锦上添花、如虎添翼的'术';基础薄弱了,框架终将成为限制能力、阻碍理解的'桎梏'。前端的核心竞争力,在于对底层本质的认知深度,而非对表面工具的熟练度。铸万丈楼台,必先深掘其基;驭时代风云,终需探得本原。
一、performance相关
我们都知道这个API是与性能相关的,Performance接口可用于获取当前页面中与性能相关的信息。一般用这个API相关的接口来计算FCP、LCP、FIP等性能指标的。但是我发现这个API不光可以计算性能指标,还可以用来计算请求的耗时,假如你在做前端监控的工具,不妨可以考虑使用一下这个API。PerformanceResourceTiming
接口允许检索和分析应用程序资源加载的详细网络计时数据。应用程序可以使用这些计时指标来确定获取特定资源如 XMLHttpRequest、svg、图像或脚本所需的时间。
接下来就是知识点了,当用performance.getEntriesByType('resource')用来获取资源条目的时候,这个函数返回的是一个PerformanceEntry数组,但这个数组有个默认大小----250 The specification requires the resource timing buffer initially to be 250 or greater;超过250时,就再也写不进去了。那要怎么办呢?有两种方式,假设你的前端项目的资源请求不是很多,那么你就可以使用setResourceTimingBufferSize(maxSize)来扩充,setResourceTimingBufferSize()方法设置存储资源类的性能条目在浏览器资源缓冲区的所需大小的。
ini
performance.setResourceTimingBufferSize(500);
如果您将缓冲区大小设置为小于缓冲区中当前条目数量的数字,则不会删除任何条目。
假设你有很多请求资源,你可以使用resourcetimingbufferfull 事件,当浏览器的资源缓冲区已满时,会触发该事件,那么我们可以使用监听事件,然后结合clearResourceTimings() 和 setResourceTimingBufferSize(maxSize)来操作资源缓冲池。
javascript
addEventListener("resourcetimingbufferfull", (event) => {
performance.clearResourceTimings();
})
这样操作会不会丢失数据?测试验证下来没有出现丢失数据的情况。用来计算的请求耗时也是准确的,基本上就是浏览器显示的耗时。
二、cookie相关
cookie在同一个父域名下是共享的,假设你有父业面和子页面,然后你们都有一个共同的顶级域名,那么你想这两个页面通信、共享非名感数据什么的,就可以写在cookie中。
ini
document.cookie = 'key=value;domain="父级域名"'
设置cookie的过期时间或失效时间,这里有个冷门的知识点---世界末日:对于永久 cookie 我们用了Fri, 31 Dec 9999 23:59:59 GMT
作为过期日。如果你不想使用这个日期,可使用世界末日Tue, 19 Jan 2038 03:14:07 GMT,
它是 32 位带符号整数能表示从 1 January 1970 00:00:00 UTC 开始的最大秒长 (即01111111111111111111111111111111
, 是 new Date(0x7fffffff * 1e3)
) .
还有个知识点就是我发现我的cookie设置的是永久时间作为过期时间,但是为什么浏览器显示的过期时间却是400天后的时间为过期时间?
原因就是chrome根据草案在104版本之后做出了调整,具体可以看Cookie Expires/Max-Age attribute upper limit这个文档,所以你不管设置永久还是世界末日,chrome都给你显示的是400天后过期。
关于expires和max-age我们不做过多解释,有兴趣的可以去MDN上去查看文档。
三、http相关
同学们有没有想过,我们每天都在写的ajax请求,它的响应头或者请求头最大可以设置多少呢?如果过大会怎么样呢?
基于这样的问题我测试了一下,发现在chrome浏览器上,如果响应Header的大小超过256KB,浏览器会抛出一个ERR_RESPONSE_HEADERS_TOO_BIG。如果响应头过大会不会影响请求的耗时呢?基于这个问题我们监听readystatechange事件,分别在readystate的1、2、3、4中验证耗时情况,发现响应头过大的话会影响请求的耗时,基本上能有几毫秒的差距。
四、计算字符串所占的内存字节数
我们一般是不是直接用length来计算长度,判断是不是超长,但是一旦字符串出现中文发现计算会有问题。这是因为我们的中文一般会占一到四个字节,那么要怎么确定字符串具体的长度么?当然大可不必像下面的代码那样去计算,但有时候我们需要计算请求报文的大小,过大会把我们的服务干爆啊,所以没办法就需要精确计算出这一串报文的大小。
ini
/**
* 所占字节数
*
* UTF-8 一种可变长度的Unicode编码格式,使用一至四个字节为每个字符编码(Unicode在范围 D800-DFFF 中不存在任何字符)
* 000000 - 00007F(128个代码) 0zzzzzzz(00-7F) 一个字节
* 000080 - 0007FF(1920个代码) 110yyyyy(C0-DF) 10zzzzzz(80-BF) 两个字节
* 000800 - 00D7FF
* 00E000 - 00FFFF(61440个代码) 1110xxxx(E0-EF) 10yyyyyy 10zzzzzz 三个字节
* 010000 - 10FFFF(1048576个代码) 11110www(F0-F7) 10xxxxxx 10yyyyyy 10zzzzzz 四个字节
* {@link https://zh.wikipedia.org/wiki/UTF-8}
*
* UTF-16 编码65535以内使用两个字节编码,超出65535的使用四个字节(JS内部,字符储存格式是:UCS-2------UTF-16的子级)
* 000000 - 00FFFF 两个字节
* 010000 - 10FFFF 四个字节
* {@link https://zh.wikipedia.org/wiki/UTF-16}
*
* GBK(ASCII的中文扩展) 除了0~126编号是1个字节之外,其他都2个字节(超过65535会由2个字显示)
* {@link https://zh.wikipedia.org/wiki/汉字内码扩展规范}
*
* @param {String} str
* @param {String} [charset= 'gbk'] utf-8, utf-16
* @return {Number}
*/
function sizeofByte (str, charset = 'gbk') {
let total = 0
let charCode
charset = charset.toLowerCase()
if (charset === 'utf-8' || charset === 'utf8') {
for (let i = 0, len = str.length; i < len; i++) {
charCode = str.codePointAt(i)
if (charCode <= 0x007f) {
total += 1
} else if (charCode <= 0x07ff) {
total += 2
} else if (charCode <= 0xffff) {
total += 3
} else {
total += 4
i++
}
}
} else if (charset === 'utf-16' || charset === 'utf16') {
for (let i = 0, len = str.length; i < len; i++) {
charCode = str.codePointAt(i)
if (charCode <= 0xffff) {
total += 2
} else {
total += 4
i++
}
}
} else {
total = str.replace(/[^\x00-\xff]/g, 'aa').length
}
return total
}