嫌JS写得不够好?我教你啊!五个小技巧
共 4179字,需浏览 9分钟
·
2021-07-05 00:02
1. 缓存——localStorage和sessionStorage
localStorage和sessionStorage是现代web开发非常好用的功能。二者到底是什么呢?我们看看mdn上对他们的介绍
“These mechanisms are available via the Window.sessionStorage and Window.localStorage properties (to be more precise, in supporting browsers the Window object implements the WindowLocalStorage and WindowSessionStorage objects, which the localStorage and sessionStorage properties hang off) — invoking one of these will create an instance of the Storage object, through which data items can be set, retrieved and removed. A different Storage object is used for the sessionStorage and localStorage for each origin — they function and are controlled separately.”
大概意思是——这些机制可以通过Window使用。sessionStorage和窗口。localStorage属性(更准确地说,在支持的浏览器窗口对象实现了WindowLocalStorage和WindowSessionStorage对象,localStorage和sessionStorage属性挂断电话)调用其中的一个将创建存储对象的一个实例,通过这些数据项可以设置、检索和删除。不同的Storage对象用于sessionStorage和localStorage,它们分别起作用和控制。
说了一大堆其实用起来很简单,设置key和value存在浏览器缓存文件中下次可以再用。
虽然缓存很好用,但是这些API是同步的。也就是说,调用这个接口的时候主线程会被占用。此外,不管是localStorage还是sessionStorage都只能存字符串。用的时候记得要序列化和反序列化(JSON.parse和JSON.stringify)
举例:
const startTime = performance.now();
const testData = Array(1000).fill(true);
store data
localStorage.setItem('foo', JSON.stringify(testData));
retrieve data
const storedData = JSON.parse(localStorage.getItem('foo'));
const endTime = performance.now();
console.log(`time ${endTime - startTime} ms.`);
在多次调用的情况下会发现有明显的卡顿。这是因为读取缓存IO操作会有较大的性能开销,多次IO操作导致卡顿。
这个时候可以在内存中做个缓存,比如:
const cache = {};
export const getStorageValue = (key) = {
if (cache[key]) {
return cache[key];
}
const value = localStorage.getItem(key);
return value === null value JSON.parse(value);
};
export const setStorageValue = (key string, value unknown) = {
cache[key] = value;
localStorage.setItem(key, JSON.stringify(value));
};
可以解决一部分问题,当然具体使用场景要具体分析。
2. 使用web的Observe API
有时候,会有这样这样一个场景:有一个滚动的窗口,你要监听某些元素是否在屏幕某个位置。一般情况下,你是要监听scroll事件,然后在进行一些计算来判断是否满足条件。scroll事件不断触发,你需要不断计算,此时又合适用防抖来减少性能消耗,节流可能可以,但是,有没有更好的办法呢?有,那就是 Observe API
比如,IntersectionObserver,MutationObserver,ResizeObserver,分别用在是否可见,HTML文档是否被更改,元素的边框或者尺寸是否被修改。
(浏览器兼容性如下图,可以看到除了IE以外主流浏览器都是支持的)
3.接受提前返回
用if写判断并返回一个值的时候,我们经常给返回的值先存在一个变量中,等到所有判断结束后再统一返回这个变量,比如:
function calItem(i) {
let result = undefined;
if (i % 15== 0) {
result = 'FizzBuzz';
} else if (i % 3 == 0) {
result = 'Fizz';
} else if (i % 5 == 0) {
result = 'Buzz';
} else {
result = i;
}
return result;
}
其实,没必要。
在这种简单的情况下,可以直接返回终止函数。
function calcItem(i) {
if (i % 15 == 0) {
return 'FizzBuzz';
}
if (i % 3 == 0) {
return 'Fizz';
}
return (i % 5 == 0) 'Buzz' i;
}
这样看起来也更清爽,易懂,好改。
我知道,在某些关于code refactor或是一些基础教程中建议你按照上面的写法,一个函数只有一个出口比较方便,尤其是在C语言这种命令式语言中。但是在Js中我们经常不断拆分复杂函数,使得每个功能块尽可能短,在这种情况下,可以说,没必要。直接返回,干净清爽。
书是死的,人是活的。照着死规矩一成不变才是大忌。切记。
4.掌握 Async 和 Defer
你的页面里,script是怎么解析是非常重要的一件事情。用户进到你的网站后,script的解析处于竞争状态,所以你得了解你的script按照什么顺序执行才行,不然可能会有意想不到的Bug。
有三个选项:default,async,还有defer。default是默认的意思。得到script,执行。此时解析度进程会暂停,直到你脚本执行好后再继续。async,异步。页面解析和脚本执行同时进行。defer,等待。脚本则在页面解析完成后才开始。
理解什么时候脚本被执行非常重要。
根据经验,相互之间没有依赖的脚本标记async并行执行就好了。有依赖的话标上defer依次执行。
5.推迟非立即需要执行的任务
JavaScript是单线程异步的。所以有哪些代码不需要马上执行的,可以推迟点执行。降低优先级,让资源先用在高优先级的地方。
怎么操作呢?
有个好东西叫requestIdleCallback。看看MDN是怎么介绍的
“The window.requestIdleCallback() method queues a function to be called during a browser’s idle periods. This enables developers to perform background and low priority work on the main event loop, without impacting latency-critical events such as animation and input response.” — MDN Web Docs
大概是说,requestidlecallback()方法将在浏览器空闲期间调用的函数排成队列。这使得开发人员能够在主事件循环上执行后台和低优先级的工作,而不会影响延迟关键事件,如动画和输入响应。
可以在许多情况下应用此策略。其中最常见的是发送分析信息。我们不介意数据是早到还是晚到。这是一个非关键任务,因为它将由另一个服务异步处理。
比如:
const handleId = window.requestIdleCallback(() = {
Analytics.sendEvent('purchaseProduct'....);
}, {
timeout 2000
});
在这个例子中,我们将等待浏览器空闲时来执行我们的Analytics代码。如果这在接下来的两秒内没有发生,它无论如何都会被执行。超时时间为可选选项。它可以帮助您进一步定制代码的执行。如果该选项不存在,它只会在浏览器有时间时执行。
以上5个JS 小技巧,如果您认为对您有帮助,请记得 点赞、留言、分享和收藏 哦~~