1.类型判断
❝核心使用 Object.prototype.toString.call(object) 方法,基本类型和引用类型都适用,比如Array,Date等。
❞
/**
* @param {any} target
* @param {string} type
* @return {boolean}
*/
function isType(target, type) {
let targetType = Object.prototype.toString.call(target).slice(8, -1).toLowerCase();
return targetType === type.toLowerCase();
}
例子:
isType([], 'Array'); // true
isType(/\d/, 'RegExp'); // true
isType(new Date(), 'Date'); // true
isType(function(){}, 'Function'); // true
isType(Symbol(1), 'Symbol'); // true
2.对象转数组
❝Array.prototype.slice.call(arguments)能将有length属性的对象转换为数组(特别注意: 这个对象一定要有length属性). 但有一个例外,IE下的节点集合它不能转换(因为IE下的dom对象是以com对象的形式实现,js对象和com对象不能进行转换)
❞
/**
* @param {object} target
* @param {number} begin
* @param {number} end
* @return {any[]}
*/
function toArray(target, ...extra) {
return Array.prototype.slice.call(target, extra);
}
例子:
let obj = {
length: 2,
0: 'first',
1: 'second'
};
toArray(obj); // ['first', 'second']
toArray(obj, 1); // ['second']
toArray(obj, 0, 1); // ['first', 'second']
3.对象属性删除
/**
* @param {object} target
* @param {string[]} props
* @return {object}
*/
function omit(target, props = []) {
if (!props.length) return target;
let result = {};
Object.keys(target).forEach(key => {
if (!props.includes(key)) {
result = {
...result,
[key]: target[key]
};
}
});
return result;
}
例子:
let obj = {
name: 'sky',
age: 25,
sex: 'man'
};
omit(obj, ['name']); // { age: 25, sex: 'man' }
4.时间格式化
/**
* @param {string} format
* @param {number} timestamp
* @return {string}
*/
function formatDate(format='Y-M-D h:m', timestamp=Date.now()){
let date = new Date(timestamp);
let dateInfo = {
Y: date.getFullYear(),
M: date.getMonth()+1,
D: date.getDate(),
h: date.getHours(),
m: date.getMinutes(),
s: date.getSeconds()
};
let formatNumber = (n) => n > 10 ? n : '0' + n;
let result = format
.replace('Y', dateInfo.Y)
.replace('M', dateInfo.M)
.replace('D', dateInfo.D)
.replace('h', formatNumber(dateInfo.h))
.replace('m', formatNumber(dateInfo.m))
.replace('s', formatNumber(dateInfo.s));
return result;
}
例子:
formatDate(); // "2020-2-24 13:44"
formatDate('M月D日 h:m'); // "2月24日 13:45"
formatDate('h:m Y-M-D', 1582526221604); // "14:37 2020-2-24"
5.url参数截取
/**
* @param {string} target
* @return {string}
*/
function getUrlParams(target) {
const str = location.search.substr(1);
if (!str) return '';
const index = str.split('&').findIndex(item => item.includes(`${target}=`));
return str.split('&')[index].split('=')[1];
}
例子:
// http://www.jianshu.com/search?q=123&page=1&type=note
getUrlParams('q'); // "123"
6.性能分析
❝Web Performance API允许网页访问某些函数来测量网页和Web应用程序的性能,performance.timing 包含延迟相关的性能信息,performance.memory 包含内存信息,是Chrome中添加的一个非标准扩展,在使用时需要注意
❞
window.onload = function() {
setTimeout(() => {
let t = performance.timing,
m = performance.memory;
console.table({
'DNS查询耗时': (t.domainLookupEnd - t.domainLookupStart).toFixed(0),
'TCP链接耗时': (t.connectEnd - t.connectStart).toFixed(0),
'request请求耗时': (t.responseEnd - t.responseStart).toFixed(0),
'解析dom树耗时': (t.domComplete - t.domInteractive).toFixed(0),
'白屏时间': (t.responseStart - t.navigationStart).toFixed(0),
'domready时间': (t.domContentLoadedEventEnd - t.navigationStart).toFixed(0),
'onload时间': (t.loadEventEnd - t.navigationStart).toFixed(0),
'js内存使用占比': m ? (m.usedJSHeapSize / m.totalJSHeapSize * 100).toFixed(2) + '%' : undefined
});
});
}
7.随机字符串
❝应用场景 React 列表的 key。
❞
/**
* @return {string}
*/
function uuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0,
v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
}).toUpperCase();
}
例子:
uuid(); // "B0578B1A-1512-42DC-8996-887E9D2C56AA"
8.生成一周时间
❝new Array 创建的数组只是添加了length属性,并没有实际的内容。通过扩展后,变为可用数组用于循环
❞
/**
* @return {string[]}
*/
function getWeekTime(){
return [...new Array(7)].map((j,i)=> new Date(Date.now()+i*8.64e7).toLocaleDateString());
}
例子:
getWeekTime(); // ["2020/8/9", "2020/8/10", "2020/8/11", "2020/8/12", "2020/8/13", "2020/8/14", "2020/8/15"]
9.防抖
❝触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
❞
应用场景
- 搜索框搜索输入。只需用户最后一次输入完,再发送请求。
- 手机号、邮箱验证输入检测。
- 窗口大小Resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
function debounce(fn) {
let timeout = null; // 创建一个标记用来存放定时器的返回值
return function () {
if (timeout !== null)clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉
timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
fn.apply(this, arguments);
}, 500);
};
}
例子:
function sayHi() {
console.log('防抖成功');
}
const inp = document.getElementById('inp');
inp.addEventListener('input', debounce(sayHi));
10.节流
❝高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率
❞
应用场景
- 滚动加载,加载更多或滚到底部监听。
- 谷歌搜索框,搜索联想功能。
- 高频点击提交,表单重复提交。
function throttle(fn) {
let canRun = true; // 通过闭包保存一个标记
return function () {
if (!canRun) return; // 在函数开头判断标记是否为true,不为true则return
canRun = false; // 立即设置为false
setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
fn.apply(this, arguments);
// 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉
canRun = true;
}, 500);
};
}
例子:
function sayHi(e) {
console.log(e.target.innerWidth, e.target.innerHeight);
}
window.addEventListener('resize', throttle(sayHi));