偶尔一问
zKing 2020-07-12
摘要
因为做不到每日一题,所以就干脆叫做“偶尔一问”了
# 什么是防抖和节流,究竟应该怎么实现
防抖和节流都是为了解决“某个函数在短时间内被重复调用”而导致的“性能问题”
# 防抖
基本概念:在事件被触发 n 秒后再执行回调函数,如果在这 n 秒内有被触发,则重新计时
常见场景
- window resize
- 用户输入后进行实时校验
function debounce(func, delay) {
let timer = null;
return function(...args) {
timer && clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
# 节流
基本概念:规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内该事件被触发多次,只能有一次生效
常见场景
- scroll 懒加载
- 重复提交数据
function throttle(func, delay) {
let timer = null;
return function(...args) {
if (!timer) {
timer = setTimeout(() => {
timer && clearTimeout(timer);
func.apply(this, args);
}, delay);
}
};
}
# 对比
- 节流是在一定的时间间隔内只允许执行一次事件
- 防抖是触发某个事件后,在一定的时间间隔后执行某个回调函数。如果在这段间隔内,事件再被触发,就重新开始
# 如何快速滚动到某个区域/某个锚点
- 借助
<a>
标签,用 href 属性加 Id 选择器的方式利用浏览器自身的机制进行锚点跳转 - 使用 js 借用点击事件,获取当前点击区域距离页面顶部的 Top 和 Left, 再和需要锚点元素通过 js 计算距离来滚动页面
- 借助浏览器新的 DOM API scrollIntoView 快速滚动到当前可视区域
# void 运算符
偶尔看到有这么写的一段 js 代码
let a = void 0; // 等价于 => let a = undefined
当时我就觉得有点奇怪,为什么一直都没有学到过 void 运算符呢?所以去翻了以下 MDN 了解相关的知识,再去找了相关资料,才发现,原来在旧版本的浏览器里,undefined
是能被重新赋值的,在被重新赋值后,直接使用 undefined
将不能被正常使用了,好在这一行为在 2009 年的 ECMAScript 5 修复了。所以现代浏览器里 undefined
是无法被重写的
所以以前的开发者为了兼容浏览器,会直接用 void 0
的方式来设置 undefined
,判断条件中也并不能直接使用 typeof x === "undefined"
这种写法,而是直接再封装成一个函数处理
function isUndefined(value) {
//获得undefined,保证它没有被重新赋值
var undefined = void 0;
return value === undefined;
}
# js 判断一个数字是否为整数
开发的时候遇到有需求,输入的数字一定要为整数才行,那就需要增加"是否为整数"的判断,这是可以借助 ES6 中 Number.isInteger
这个函数来处理。那如果不使用 ES6,还有多少种方式呢?
- 借助数学,我们知道整数对 1 进行求余肯定为 0,所以可以封装函数如下
function isInteger(num) {
return typeof num === "number" && num % 1 === 0;
}
- 既然借助数学了,那是不是可以用 Math 中的方法来判断?当然可以
function isInteger(num) {
return typeof num === "number" && Math.floor(num) === num;
}
- 转为整数我们可以使用
parseInt
函数,那也能可以作为判断条件
function isInteger(num) {
return typeof num === "number" && parseInt(num, 10) === num;
}
- 既然是整数,那是不是还可以转成字符串再切割,不是小数的就是整数了嘛
function isInteger(num) {
return typeof num === "number" && String(num).indexOf(".") === -1;
}
所以可以使用 6 种方法来判断数字是否为整数,但是,后面查了资料,发现还可以借助"位运算"的方式来判断,这倒是从来没有设想过,写法如下
function isInteger(num) {
return (num | 0) === num;
}
但该方法有个问题,位运算只能处理 32 位以内的数字,超过就无能为力了