数组遍历方法实现记录
Aug 22, 2021
# JS
深拷贝、遍历、防抖、节流方法实现
# 浅拷贝
- Object.assign()
- Array.prototype.concat()
- Array.prototype.slice()
- ES6 扩展运算符
# 深拷贝
# cloneDeep
js
function cloneDeep(origin, hashMap = new WeakMap()) {
// 非 undefined null 引用值,返回 origin
if (origin == undefined || typeof origin !== 'object') {
return origin;
}
// 日期对象
if (origin instanceof Date) {
return new Date(origin);
}
// 正则对象
if (origin instanceof RegExp) {
return new RegExp(origin);
}
// hashMap 中是否已存在本次要拷贝的对象 origin
const hashKey = hashMap.get(origin);
// 存在,返回该对象
if (hashKey) {
return hashKey;
}
// 对象和数组通过 origin 构造器新建
const target = new origin.constructor();
// 将对象存入hashMap
hashMap.set(origin, target);
// 遍历 origin 对象
for (let k in origin) {
// 排除 prototype 上的属性
if (origin.hasOwnProperty(k)) {
// 递归处理嵌套对象
target[k] = cloneDeep(origin[k], hashMap);
}
}
// 返回深拷贝后的对象
return target;
}
const test1 = {};
const test2 = {};
test1.test2 = test2;
test2.test1 = test1;
const res = cloneDeep(test1);
console.log(res);
使用WeakMap
解决相互引用的对象,在深拷贝过程中被重复克隆,从而引起Maximum call stack size exceeded
的问题。与Map
不同的是WeakMap
的key
只能是一个引用类型,这也是WeakMap
中垃圾回收的意义所在。
# weakMap
js
const oBtn1 = document.querySelector("#btn1");
const oBtn2 = document.querySelector("#btn2");
// 创建WeakMap
const oBtnMap = new WeakMap();
// 弱引用
oBtnMap.set(oBtn1, handleBtn1Click);
oBtnMap.set(oBtn2, handleBtn2Click);
// 绑定事件处理函数
oBtn1.addEventListener("click", oBtnMap.get(oBtn1), false);
oBtn2.addEventListener("click", oBtnMap.get(oBtn2), false);
function handleBtn1Click() {}
function handleBtn2Click() {}
// 移除DOM
oBtn1.remove();
oBtn2.remove();
# array-methods
# forEach
js
Array.prototype.myForEach = function (cb) {
var _arr = this;
var _len = _arr.length;
var _arg2 = arguments[1] || window;
var _item;
for (var i = 0; i < _len; i++) {
_item = cloneDeep(_arr[i]);
cb.apply(_arg2, [_item, i, _arr]);
}
}
# map
js
Array.prototype.myMap = function (cb) {
var _arr = this;
var _len = _arr.length;
var _arg2 = arguments[1] || window;
var _item;
var _newArr = [];
for (var i = 0; i < _len; i++) {
_item = cloneDeep(_arr[i]);
_newArr.push(cb.apply(_arg2, [_item, i, _arr]));
}
return _newArr;
}
# filter
js
Array.prototype.myFilter = function (cb) {
var _arr = this;
var _len = _arr.length;
var _arg2 = arguments[1] || window;
var _item;
var _newArr = [];
for(var i = 0; i < _len; i++) {
_item = cloneDeep(_arr[i]);
cb.apply(_arg2, [_item, i, _arr])
? _newArr.push(_item)
: '';
}
return _newArr;
}
# every
js
Array.prototype.myEvery = function (cb) {
var _arr = this;
var _len = _arr.length;
var _arg2 = arguments[1] || window;
var _item;
var _res = true;
for (var i = 0; i < _len; i++) {
_item = cloneDeep(_arr[i]);
if (!cb.apply(_arg2, [_item, i, _arr])) {
_res = false;
break;
};
}
return _res;
}
# some
js
Array.prototype.mySome = function (cb) {
var _arr = this;
var _len = _arr.length;
var _arg2 = arguments[1] || window;
var _item;
var _res = false;
for (var i = 0; i < _len; i++) {
_item = cloneDeep(_arr[i]);
if (cb(_arg2, [_item, i, _arr])) {
_res = true;
break;
}
}
return _res;
}
# reduce
js
Array.prototype.myReduce = function (cb, initialVal) {
var _arr = this;
var _len = _arr.length;
var _arg3 = arguments[2] || window;
var _item;
for (var i = 0; i < _len; i++) {
_item = cloneDeep(_arr[i]);
initialVal = cb.apply(_arg3, [initialVal, _item, i, _arr]);
}
return initialVal;
}
# reduceRight
js
Array.prototype.myReduceRight = function (cb, initialVal) {
var _arr = this;
var _len = _arr.length;
var _arg3 = arguments[2] || window;
var _item;
for (var i = _len - 1; i >= 0; i--) {
_item = cloneDeep(_arr[i]);
initialVal = cb.apply(_arg3, [initialVal, _item, i, _arr]);
}
return initialVal;
}
# 防抖、节流
# 防抖
js
function debounce(fn, delay) {
let timer = null;
return function () {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null;
}, delay);
};
}
# 节流
js
function throttle(fn, delay) {
let timer = null;
return function () {
if (timer) {
return;
}
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null;
}, delay);
};
}