工具方法
{ { xxx } }
的内容替换成 data[xxx]
将字符串中 function stringfy(str, data) {
return str.replace(/\{\{[^\}\}]+\}\}/g, function(v) {
console.log(v);
let key = v.substring(2, v.length - 2);
return data[key] || v;
});
}
模拟耗时操作
有时候自己在做一些测试的时候,需要来模拟一个耗时的操作。
一开始总是用 while true ,执行一个很大的循环来模拟。这种方法对耗时的时间无法精确控制。
后面无意中想到了这种方法
//耗时操作,大概1秒
function sleep(sleepTime = 1500) {
var start = new Date().getTime();
while (true) {
if (new Date().getTime() - start > sleepTime) {
break;
}
}
//console.log('sleep done')
}
数组分块
由于 js 是单线程的,有时候一个耗时的操作会阻塞线程,导致这段时间用户无法与界面交互。
如果是某个循环比较耗时,并且该循环并不必须同步完成,就可以使用数组分块的技术,小块小块的处理数组,给主线程有空闲的机会,就可以不影响用户的操作。
实现数组分块非常简单:
/**
* 数组分块
* array : 数组
* process :处理程序
* context : 上下文
*/
function chunk(array, process, context) {
setTimeout(function loop() {
var item = array.shift();
process.call(context, item);
if (array.length > 0) {
setTimeout(loop, 100);
}
}, 100);
}
TIP
一旦某个函数需要花 50ms 以上的时间完成,就可以考虑能否分隔成多个小任务来完成
浅拷贝
浅拷贝是指复制对象的第一层
//es5
function shallowClone(source) {
var target = {};
for (var key in source) {
if (source.hasOwnProperty(key)) {
target[key] = source[key];
}
}
return target;
}
TIP
在 es6 中,直接使用 {...source}
或者 Object.assign({},source);
即可
深拷贝
深拷贝是指一层一层的拷贝对象或数组。
主要注意点是防止循环引用,
例如 :
let obj = {} ; let obj2 = {}; obj.a = obj2;
这种情况下,深拷贝需要打破循环引用,防止死循环
// 深拷贝 es6版本
export function deepCopy(source) {
// hash表,记录所有的对象的引用关系
let copyedMap = new WeakMap();
let isArray = target => target instanceof Array;
let isObject = target => target instanceof Object;
// 遍历方法,支持数组与对象
let each = function(list, callback) {
if (isArray(list)) {
list.forEach(callback);
} else if (isObject(list)) {
let keys = Object.keys(list);
keys.forEach(key => {
callback(list[key], key, list);
});
}
};
// 拷贝方法
let copy = function(item) {
if (isArray(item) || isObject(item)) {
// 检查是否循环引用,防止死循环
let existed = copyedMap.get(item);
if (existed) {
return existed;
}
// 递归拷贝
let result = isArray(item) ? [] : {};
copyedMap.set(item, result);
each(item, (value, key) => {
result[key] = copy(value);
});
return result;
} else {
return item;
}
};
return copy(source);
}
多次触发才真正执行
在一定的时间间隔内,触发到一定次数。才真正调用处理函数
/**
* 包装一个函数,在一定时间里触发了一定次数之后,才触发
* @param count 次数
* @param wait 时长
* @param func 触发的方法
* @param context 上下文
*/
export function repeatAfter(count, wait, func, context = null) {
let timer = null;
let num = 0;
return function(...args) {
// 清空timer
if (timer) {
clearTimeout(timer);
timer = null;
}
// 增加数量
num++;
console.log(`tap num --> ${num}`);
if (num >= count) {
func.apply(context, args);
}
// 多少秒后还未进入就清0
timer = setTimeout(() => {
num = 0;
}, wait);
};
}