本人是一个web前端开发工程师,主要是vue框架,整理了一些面试题,今后也会一直更新,有好题目的同学欢迎评论区分享 ;-)
web面试题专栏:点击此处
文章目录
深拷贝和浅拷贝的区别
在JavaScript中,深拷贝和浅拷贝是两种不同的对象复制方式。
浅拷贝是指将一个对象的引用复制给另一个对象,这意味着两个对象将共享相同的内存地址。当修改其中一个对象时,另一个对象也会受到影响。
深拷贝是指创建一个新的对象,并将原始对象的所有属性逐个复制到新对象中。这意味着两个对象是完全独立的,修改其中一个对象不会影响另一个对象。
浅拷贝示例
js
let obj1 = { name: "Alice", age: 25 };
let obj2 = obj1; // 浅拷贝
obj2.name = "Bob";
console.log(obj1.name); // 输出: Bob,因为obj1和obj2共享相同的引用
深拷贝示例
js
let obj1 = { name: "Alice", age: 25 };
let obj2 = JSON.parse(JSON.stringify(obj1)); // 深拷贝
obj2.name = "Bob";
console.log(obj1.name); // 输出: Alice,因为obj1和obj2是完全独立的对象
在上面的深拷贝示例中,我们使用 JSON.stringify() 将原始对象转换为字符串,然后使用 JSON.parse() 将字符串转换回对象。这样做可以创建一个新的对象,并将原始对象的属性逐个复制到新对象中,从而实现深拷贝。
需要注意的是,深拷贝有时可能会有性能和内存消耗的问题,尤其是对于包含循环引用或大量嵌套对象的复杂对象。因此,在选择深拷贝或浅拷贝时,需要根据具体情况进行权衡。
特殊对象属性
- RegExp:不能拷贝
- Date:时间对象会转换成字符串
- Error:错误对象会转换成{}
- Symbol:不能拷贝
- Function:不能拷贝
测试对象如下:
js
var obj = {
name: "penk",
age: 30,
boo: true,
n: null,
un: undefined,
sy: Symbol("penk value"),
// big: 10n, // 浏览器没这个,nodejs可以
child: {
name: "penk son",
},
arr: [1, 2, 3, 4],
reg: /^\d+$/,
fn: function () {
console.log(this.name);
},
time: new Date(),
err: new Error("蛋疼"),
};
JSON.parse(JSON.stringify(obj));
obj对象
JSON转换对象
虽说是深拷贝,但是有些属性不行。
obj与JSON转换对象对比
手写深拷贝
封装好deepCopy
- 处理了特殊对象属性的拷贝
- 对于循环引用,进行了(WeekMap)去重处理。
js
// 深拷贝函数
// 避免对象中存在重复应用的优化方案
// 通过set集合的方式,obj不同才会进行操作
function deepCopy(obj, treated = new WeakMap()) {
// null 也是一个对象...
// 不是对象就返回,数组也是对象~
if (obj == null || typeof obj !== "object") return obj;
// 对象的类型
// console.log => '[object Object]' '[object Array]'
let string = Object.prototype.toString.call(obj);
// 对象的构造函数
let ctor = obj.constructor;
// 如果有这个obj这个键名,则直接返回键值
if (treated.has(obj)) return treated.get(obj);
let newObj = {};
// 是个复合数据类型,放的是地址
treated.set(obj, newObj);
if (string.includes("Object")) {
// for of 不能遍历普通对象,只能遍历iterator 对象
for (let i in obj) {
newObj[i] = deepCopy(obj[i], treated);
}
return newObj;
} else if (string.includes("Array")) {
// 是数组
for (let i = 0; i < obj.length; i++) {
newObj[i] = deepCopy(obj[i], treated);
}
} else if (string.includes("RegExp")) {
// 是正则对象
newObj = new ctor(obj);
} else if (string.includes("Date")) {
// 是日期对象
newObj = new ctor(obj);
} else if (string.includes("Error")) {
// 是Error对象
newObj = new ctor(obj.message);
} else if (string.includes("Symbol")) {
// 是Symbol对象
newObj = new ctor(obj.description);
} else if (string.includes("Function")) {
// 是方法
newObj = function (...arg) {
target.call(this, ...arg);
};
}
return newObj;
}
打印如下: