深拷贝
原生版
const obj = {
name: "tianzhen",
};
const newObj = JSON.parse(JSON.stringify(obj));
newObj.age = 18;
console.log("==================", newObj);
console.log("==================", obj);
改变newObj不会影响到obj
- JSON.stringify存在的问题
const obj = {
a: undefined,
b: null,
c: "tianzhen",
d: function () {},
e: [1, 2, 3],
f: Symbol("1"),
[Symbol("1")]: "symbol",
};
const newObj = JSON.parse(JSON.stringify(obj));
console.log("newObj==================", newObj);
// {
// "b": null,
// "c": "tianzhen",
// "e": [
// 1,
// 2,
// 3
// ]
// }
- undefined, 函数, Symbol作为属性值的时候会直接忽略,Symbol作为key也会忽略
- Date对象会变成字符串
- RegExp对象会变成空对象{}
- 存在循环引用会报错
基础版
const obj = {
name: "tianzhen",
getName: function () {
console.log(this.name);
},
friends: ["lisi", "wangwu"],
};
function deepCopy(originObj) {
if (typeof originObj !== "object" && !originObj) {
return;
}
const target = Array.isArray(originObj) ? [] : {};
for (let key in originObj) {
if (Object.hasOwnProperty.call(originObj, key)) {
target[key] = typeof originObj[key] === "object" ? deepCopy(originObj[key]) : originObj[key];
}
}
return target;
}
升级版
主要是解决循环引用
const obj = {
name: "tianzhen",
age: undefined,
getName: function () {
console.log(this.name);
},
friends: ["lisi", "wangwu"],
};
obj.info = obj; // 添加循环引用
function deepCopy(originObj, map = new WeakMap()) {
if (typeof originObj !== "object" && !originObj) {
return;
}
if (map.has(originObj)) {
return map.get(originObj);
}
const target = Array.isArray(originObj) ? [] : {};
map.set(originObj, target);
for (let key in originObj) {
if (Object.hasOwnProperty.call(originObj, key)) {
target[key] =
typeof originObj[key] === "object" ? deepCopy(originObj[key], map) : originObj[key];
}
}
return target;
}
再升级
function getType(obj) {
const type = Object.prototype.toString.call(obj).slice(8, -1);
return type;
}
function deepCopy(originObj, map = new WeakMap()) {
if (getType(originObj) === "RegExp") {
return new RegExp(originObj);
}
if (getType(originObj) === "Date") {
return new Date(originObj);
}
if (typeof originObj === "symbol") {
return Symbol(originObj.description);
}
if (typeof originObj !== "object" || originObj === null) {
return originObj;
}
if (map.has(originObj)) {
return map.get(originObj);
}
let target = Array.isArray(originObj) ? [] : {};
map.set(originObj, target);
for (const key in originObj) {
target[key] = deepCopy(originObj[key], map);
}
return target;
}
柯里化
- 只传给函数一部分参数来调用它,返回一个函数再处理剩余参数
- 这个过程就称为柯里化
// 实现一
function add(x, y, z) {
return x + y + z;
}
add(1, 2, 3);
add(1)(2)(3); // 实现类似这种调用
function currying(fn) {
function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
// 参数不足时需要返回一个函数
return function (...args2) {
return curried.apply(this, [...args, ...args2]);
};
}
}
return curried;
}
// 实现二
function currying(fn, ...args) {
return fn.length <= args.length ? fn.apply(this, args) : currying.bind(this, fn, ...args);
}
数组扁平化(拍平)
// 实现一
let arr = [1, [2, [3, 4, 5]]];
function flatten(arr) {
let result = [];
arr.forEach((item) => {
if (Array.isArray(item)) {
result = result.concat(flatten(item)); // 递归
} else {
result.push(item);
}
});
return result;
}
// 实现二(reduce)
let arr = [1, [2, [3, 4, 5]]];
function flatten(arr) {
return arr.reduce((prev, next) => {
prev.concat(Array.isArray(next) ? flatten(next) : next);
}, []);
}
数组乱序
// 方法一
const arr = [1, 2, 3, 4, 5, 6];
arr.sort(() => {
return Math.random() - 0.5;
});
// 方法二
const arr = [1, 2, 3, 4, 5, 6];
let len = arr.length;
while (len !== 0) {
const randomIndex = parseInt(Math.random() * len);
len--;
[arr[len], arr[randomIndex]] = [arr[randomIndex], arr[len]];
}