首页 > 编程语言 >javascript - 练习题:浅层克隆和深层克隆

javascript - 练习题:浅层克隆和深层克隆

时间:2022-11-03 18:03:23浏览次数:43  
标签:练习题 origin obj target javascript prop 数组 var 克隆


浅层克隆

问:把 obj 对象的内容,克隆到 ojb1 上去。 

var obj = {
name : 'abc',
age: 123,
sex:"female"
}
var obj1 = {}

分析:这个没有引用值的对象,可以使用浅层克隆。

循环取属性和值(for in),赋给 ojb1 ,再封装起来。

var obj = {
name: 'abc',
age: 123,
sex: "female"
}
var obj1 = {}

function clone(Target, Origin) {
var Target = Target || {}; // 容错,用户输入了 Target 就用,没有就新建个空{}
for (var prop in Origin) {
Target[prop] = Origin[prop];
}
return Target; // 返回
}
clone(obj1, obj);

这里面有个 Target = Target || {} 的用法,用使用了 “或运算” 的特性:遇到真值就返回,意思是:

如何 Target 有值,就用这个 Target ,如果没有,那就给 Target 返回空对象 {} ,简洁,舒服;

效果如控制台:

javascript - 练习题:浅层克隆和深层克隆_浅层克隆

如果对象比较复杂一点:对象里面还有对象

var obj = {
name: 'abc',
age: 123,
sex: "female",
wife: {
name:"bcd",
age:234,
son:{
name:"cde",
age:345
}
},
card:["visa","unionpay"],
}

看一下结果:

javascript - 练习题:浅层克隆和深层克隆_浅层克隆_02

也是可以的。不过对象里有引用值,比如说有个数组的情况:

var obj = {
// ...
card:["visa","unionpay"] // 数组
}
var obj1 = {}

执行完 clone(obj1,obj)后,修改了obj1.card 的内容,也会修改 obj.card 的内容。

有时,这样就不是我们想要的克隆了。

看控制台输出 :

javascript - 练习题:浅层克隆和深层克隆_浅层克隆_03

克隆完后,给obj1.card里,push 了新值,原对象 obj.card 里也有了。

所以,把这种克隆叫浅层克隆。


深层克隆

问:把 obj 克隆到 ojb1 里,要求是不能通过 obj1 操作 obj 的内容。

var obj = {
name: 'abc',
age: 123,
sex: "female",
wife: {
name:"bcd",
age:234,
son:{
name:"cde",
age:345
}
},
card:["visa","unionpay"],
}

分析:深层克隆,就是克隆后要,长的一模一样,但就不是一个人。

对于原始值,可以直接  obj[prop] 过去,但引用值就不能这么只这么干了。

假如要克隆对象里的数组,先建个数组对象,然后再循环把数组里的值挨个取出赋给新数组。

问题是对象的属性值也可以是对象,对象里还可以有数组,该怎么弄?


思路:

遍历对象 for(var prop in obj)

1,判断是不是原始值,是就直接赋值;

2,判断是数组还是对象;

3,建立相应的数组或对象。

把原数组或对象当做一个新的对象来赋值 copy 。

数组里面也可能有引用值:就又要先判断是不是原始值,再判断是数组还是对象的过程。

这种周而复始的 123循环 看起来就像是递归。

主要来说是3步,其次是递归这3步;

看下伪代码:

var obj1 = {
name: 'abc',
// 上面三个原始值,直接 copy

// 对象:先建对象
// 看对象内部原始值,挨个 copy
// 对象里的对象也循环挨个 copy
wife: {
name:"bcd",
// ...
son:{
name:"cde",
// ...
}
},
// 数组:先建数组
// 看数组内部的原始值,挨个 copy
card:["visa","unionpay"],
}

知识点:遍历

for in 不仅能遍历对象,也能遍历数组,数组也是特殊类型的对象;

// for(var prop in obj)
var arr = ["a","b","c"];
for(var prop in arr){
arr[prop];
}

 控制台输出:

javascript - 练习题:浅层克隆和深层克隆_深层克隆_04

知识点:判断原始值

用 typeof , 如果是 object 都是 引用值;


知识点:判断数组还是对象

三种方法:

1,constructor

javascript - 练习题:浅层克隆和深层克隆_浅层克隆_05

2,instanceof

javascript - 练习题:浅层克隆和深层克隆_浅层克隆_06

3,toString

javascript - 练习题:浅层克隆和深层克隆_浅层克隆_07

看下代码:

function deepClone(origin, target) {
var target = target || {}, // 如果target没定类型,就给他{}
toStr = Object.prototype.toString, // 用于比对数组和对象
arrStr = "[object Array]"; // 数组的返回值,注意大小写

for (var prop in origin) {
if (origin.hasOwnProperty(prop)) { // 判断自有属性
if (typeof (origin[prop]) !== "null" && typeof (origin[prop]) == 'object') {
if (toStr.call(origin[prop]) == arrStr) { // 比对
target[prop] = []; // 是数组给 []
} else {
target[prop] = {}; // 是对象给 {}
}
deepClone(origin[prop], target[prop]); // 递归

} else {
target[prop] = origin[prop]; // 原始值赋值
}
}
}
return target; // 最后返回
}

看控制台输出:

javascript - 练习题:浅层克隆和深层克隆_浅层克隆_08

代码还可以用 三目运算符简化一下:

function deepClone(origin, target) {
var target = target || {}, // 如果target没定类型,就给他{}
toStr = Object.prototype.toString, // 用于比对数组和对象
arrStr = "[object Array]"; // 数组的返回值,注意大小写

for (var prop in origin) {
if (origin.hasOwnProperty(prop)) { // 判断自有属性
if (typeof (origin[prop]) !== "null" && typeof (origin[prop]) == 'object') {
target[prop] = (toStr.call(origin[prop]) == arrStr) ? [] : {}
deepClone(origin[prop], target[prop]); // 递归

} else {
target[prop] = origin[prop]; // 原始值赋值
}
}
}
return target; // 最后返回
}


标签:练习题,origin,obj,target,javascript,prop,数组,var,克隆
From: https://blog.51cto.com/ahuiok/5820641

相关文章

  • 从柯里化讲起,一网打尽 JavaScript 重要的高阶函数
    前情回顾我们在前篇​​《✨从历史讲起,JavaScript基因里写着函数式编程》​​讲到了JavaScript的函数式基因最早可追溯到1930年的lambda运算,这个时间比第一台计算......
  • javascript规范中美元符号$是什么?
    用途:一般用$获取页面中的某一个对象的id。参考:https://www.cnblogs.com/xutao1517588477/p/10582463.html>>拓展:$(function(){}),什么时候执行?https://blog.csdn.net/u0......
  • 如果我的JavaScript跑的和Java一样快
    重度应用GraalVM一年后有感; Java世界里总有一种风气,就是我要测试看数据,跑case看指标;但实际落实到指标上呢,比如一个场景,到底IO多还是CPU多,到底怎么做合适,变得模糊;所以啊......
  • javascript - 练习题(若干)
    慢慢收集一些习题、考题练习1问:X,Y,Z分别是多少?varx=1,y=z=0;functionadd(n){returnn=n+1;}y=add(x);functionadd(n){returnn=n+3;}z=add(x);conso......
  • 【笔记14】Javascript - 继承
    【笔记14】Javascript-继承继承的概念不陌生,在原型、原型链那里,就知道一个对象能继承到原型很多属性和方法。各种继承的方法有优势有不足,看下继承发展史:继承传统形式:原型......
  • JavaScript中的Object.keys的详解和用法
    目的:在实际开发中,我们有时需要知道对象的所有属性。解决办法:ES5引入了Object.keys方法,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。参考:https://......
  • Javascript 异常处理的一些经验
      写在前面 为了提升应用稳定性,我们对前端项目开展了脚本异常治理的工作,对生产上报的jserror进行了整体排查,试图通过降低脚本异常的发生频次来提升相关告警的准确......
  • Javascript进阶笔记 - BOM
    6.BOM目录6.BOM1.BOM简介2.History3.Location4.定时器1.BOM简介BOM是指游览器对象模型,BOM提供了一组对象,方便用户通过JS操作游览器BOM对象Window代表......
  • Javascript进阶笔记 - 事件
    事件目录事件1.事件相关概念2.文档的加载3.事件的冒泡4.事件的委派5.事件监听绑定1.事件相关概念事件是电脑输入设备与页面进行交互的响应。注册就是告诉游......
  • Javascript进阶笔记 - 常用事件
    常用事件目录常用事件1.onload事件2.onclick事件3.onblur事件4.onchange事件5.onsubmit事件6.onscroll事件7.onmousemove事件8.onmousedown&onmouseup事件9.on......