当前位置: 首页 > news >正文

【前端】JavaScript--浅拷贝与深拷贝

浅拷贝

复制基本类型和值

var a = 1;
b = a;
a = 2;
console.log(a, b);

2 1

深拷贝

对引用类型拷贝,会进行地址的拷贝
引用类型

var a = { c: 1 };
b = a;
a.c = 2;
console.log(a.c, b.c);

2 2

浅拷贝的实现

function shallowClone(source) {var target = {};for (var i in source) {if (source.hasObject(i)) {target[i] == source[i];}}return target;
}

上述代码相关:for in, Object.keys和Object.getOwnPropertyNames的区别

const linglingkwong = Object.create({ age: 30 });
Object.defineProperty(linglingkwong, 'sex', { value: 'female', enumerable: false });
linglingkwong[Symbol('partner')] = 'orm';  // symbol 用来表示唯一的、不可变的值
linglingkwong.own = 1;// for-in
for (const k in linglingkwong)console.log(k)  // own age -- 只枚举// Object.keys
console.log(Object.keys(linglingkwong));  // ['own'] -- 自身,可枚举// Object.getOwnPropertyNames
console.log(Object.getOwnPropertyNames(linglingkwong));  // ['sex', 'own']

为什么会出现不同的结果?
上述对象 linglingkwong 中有三种属性

  1. 原型链
  2. 不可枚举
  3. Symbol

如何区分这三种属性呢?
JavaScript 中的 Object.create() 方法用于创建一个新对象,并指定该对象的原型。
即,age 是 linglingkwong 的原型。

const linglingkwong = Object.create({ age: 30 });

创建了一个空对象,它的原型指向 {age : 30}
{age : 30}创建了一个新的匿名对象,它有一个属性age,值为30。
Object.create(...)以这个匿名对象为原型,创建了一个新对象。
const linglingkwong = ... 将这个新对象赋值给 linglingkwong

即 age 为原型。

enumerable:true时,为可枚举。它是描述内部属性的。

Symbol是对象属性的属性,它表示该属性是唯一的。

由上述结果可知:
三种方式种只有 for-in 可以访问原型链。
当内部属性为不可枚举时,不能用for-in遍历到,也不能用Object.keys访问。
上述三种方法中,只有Object.getOwnPropertySymbols(obj) 可以访问Symbol属性。

深拷贝的实现

弱点:存在爆栈问题,循环引用问题

function clone(source) {var target = {};for (var i in source) {if (source.hasOwnProperty(i)) {if (typeof source[i] === 'object') {target[i] = clone(source[i]);} else {target[i] = source[i];}}}return target;
}

不过,上述代码中仍存在一些问题。

没有对参数做检验

函数需要校验参数,不是对象的话直接返回。

if (!isObject(source)) return source;

不过上述判断是否为对象的逻辑不严谨,如果遇到null,会误判成object。
因此,采用:

if (source == null || !isObject(source)) return source;

解决循环引用的问题

if (hash.has(source)) return hash.get(source);

没有考虑数组的兼容

需要区分数组和普通对象

const  target = Array.isArray(source) ? [] : {};
hash.set (source, target);
for (const key of Reflect.ownKeys(source)){target[key] = clone(source[key], hash);
}

一行代码的深拷贝

弱点:存在循环引用问题,爆栈问题

function cloneJSON(source) {return JSON.parse(JSON.stringify(source));
}

破解循环引用

// 遍历uniqueList
function find(arr, item) {for (let i = 0; i < arr.length; i++) {if (arr[i].source === item) {return arr[i]}}return null;
}
function cloneForce(x) {const uniqueList = []; // 用来去重let root = {};// 循环数组const loopList = [{parent: root,key: undefined,data: x,}];while (loopList.length) {// 深度优先const code = loopList.pop();const parent = node.parent;const key = node.key;const data = node.data;// 初始化赋值目标 key为undefined则拷贝到父元素,否则拷贝到子元素let res = parent;if (typeof key !== 'undefined') {res = parent[key] = {};}let uniqueData = find(uniqueList, data);// 数据已经存在if (uniqueData) {parent[key] = uniqueData.target;break;}// 数据不存在// 保存数据源 在拷贝数据中对应呃引用uniqueList.push({source: data,target: res,})for (let k in data) {if (data.hasOwnProperty(k)) {if (typeof data[k] === 'object') {// 下一次循环loopList.push({parent: res,key: k,data: data[k],});} else {res[k] = data[k];}}}}return root;
}

文章转载自:

http://CQt15I3C.bmncq.cn
http://0U4N2wPx.bmncq.cn
http://zzL6iHVG.bmncq.cn
http://Z8CRNI4Q.bmncq.cn
http://OTCsJcwt.bmncq.cn
http://CRxwkzeq.bmncq.cn
http://MXpIQyf7.bmncq.cn
http://iiS43euZ.bmncq.cn
http://48MqpOtN.bmncq.cn
http://rOEAr92r.bmncq.cn
http://JUeYSgBU.bmncq.cn
http://BZiREJR4.bmncq.cn
http://ZgILk5GK.bmncq.cn
http://Xj4lrI99.bmncq.cn
http://1lnWUrJG.bmncq.cn
http://r4BV4mzQ.bmncq.cn
http://UMvPLbyq.bmncq.cn
http://fBFikDFP.bmncq.cn
http://pc9u3yFQ.bmncq.cn
http://FtelNJBR.bmncq.cn
http://UUplqSfq.bmncq.cn
http://K7Gyo2vf.bmncq.cn
http://Oqw9zkLx.bmncq.cn
http://kLoofSlc.bmncq.cn
http://L8AaN6cj.bmncq.cn
http://hhwKmA75.bmncq.cn
http://dAMswu4n.bmncq.cn
http://WgbGVJCK.bmncq.cn
http://JeXMKF1w.bmncq.cn
http://EOT4vDuT.bmncq.cn
http://www.dtcms.com/a/380374.html

相关文章:

  • pureadmin的动态路由和静态路由
  • 24年秋招-京东-后端开发岗-第1批笔试总结
  • 技术与情感交织的一生 (十三)
  • 1 环境配置
  • 老年人生活照护实训室:支撑照护实操教学的关键场所
  • 俄罗斯方块终端游戏实现 —— C语言系统编程与终端控制
  • 跨屏互联KuapingCMS建站系统发布更新 增加seo自动外链功能
  • 域账号提权后权限管理问题解析
  • Go语言设计模式(七)组合模式
  • 解密完全二叉树顺序存储之堆结构
  • 【Vue2 ✨】Vue2 入门之旅 · 进阶篇(三):模板编译原理
  • 嵌入式仿真技术在教学中的应用与挑战探析
  • Kaggle项目实践——Titanic: Machine Learning from Disaster
  • 【leetcode】127. 三角形的最小路径和
  • Java设计模式中的几种常用设计模式
  • 【Vue2 ✨】Vue2 入门之旅 · 进阶篇(四):异步更新与 nextTick 原理
  • 【小程序】微信小程序九宫格抽奖动画(完整版)
  • [BJDCTF 2020]encode
  • 系统核心解析:深入操作系统内部机制——进程管理与控制指南(一)【进程/PCB】
  • 速通ACM省铜第二天 赋源码(Adjacent XOR和Arboris Contractio)
  • Python快速入门专业版(二十四):while循环:条件循环与“死循环”避免(猜数字游戏案例)
  • 神经网络构成框架-理论学习
  • 智能眼镜产品成熟度分析框架与评估
  • 从零学算法2327
  • 【C++】:list容器全面解析
  • 渲染农场多少钱一小时
  • IDEA试用过期,无法登录,重置方法
  • IP验证学习之case编写
  • 通过Dockerfile构建Docker镜像并训练模型
  • 操作系统内核架构深度解析:从微内核到宏内核的设计哲学与性能权衡