目录 1.1 Object.assign(target,source)方法 1.2 Array.prototype.concat()方法 1.3 Array.prototype.slice(start,end)方法 2.1 JSON.parse(JSON.stringify(obj)) JavaScript中的数据分为基本类型和引用类型,一般基本类型的数据占用内存大小确定,保存于栈中;引用类型的数据由于在创建之初数据占用内存的大小不确定,但是保存数据的地址占用内存大小确定,因此引用类型的数据实体保存于堆中,按需分配,引用类型在堆中保存数据实体的起始地址保存于栈中。当解释器寻找引用类型的值时,会首先检索其在栈中的地址,取得地址后再从堆中获得数据实体。 一般来说,浅拷贝和深拷贝只是相对于引用类型的对象而言。 只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。 会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。 要点: 在对引用类型的数据进行操作的时候,到底怎样才能进行浅拷贝?怎样才能进行深拷贝呢?下面就分别介绍浅拷贝和深拷贝的实现方式。 目前,一个对象进行浅拷贝的方式有三种,分别为Object.assign(target,source)、Array.prototype.concat(source)和Array.prototype.slice(start,end)。 Object.assign(target,source) 方法可以把一个或者多个源对象(第一个参数后边的所有参数对象均为源对象)自身的可枚举属性拷贝给目标对象(第一个参数为目标对象),然后返回目标对象。但是 Object.assign(target,source)进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。【对于可枚举属性有不清楚的同学可以看看 遍历一个对象包含的可枚举属性的方法】 结果如下图所示: 特点: 案例一 结果如下图所示: 案例二 结果如下图所示: 特点 案例一 结果如下图所示: 目前,一个对象进行深拷贝的方式有三种,分别为JSON.parse(JSON.stringify(obj))、lodash函数库和手写递归方法。 该方法的原理是先将引用类型的对象转换为基础类型的字符串,然后将其从字符串再重新转换为对应的引用类型对象,在进行转换为引用对象的时候,会为对象的每个属性重新分配堆内存,即进行了深拷贝。(自己的理解) 结果如下图所示: 特点 Lodash是一个著名的javascript原生库,不需要引入其他第三方依赖。Lodash使用了一个简单的 _ 符号,就像Jquery的 $ 一样,十分简洁。lodash函数库提供 _.cloneDeep用来做深拷贝。 显示结果如下图所示: 特点 递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝。 案例一 显示结果如下图所示: 由上图可知:该方法可以对数组或者函数类型的属性进行深拷贝,但是会忽略Symbol类型和不可枚举类型的属性。 案例二 结果如下图所示: 由上图可知:对于不可枚举类型的属性也可以进行拷贝,但是需要将属性的所有描述对象属性也拷贝给新对象,避免出现虽然新对象与原对象相对应的属性都相同,但是属性描述不同的现象。 参考文献:https://blog.csdn.net/chaopingyao/article/details/105026649
一、概念
1、浅拷贝
2、深拷贝
二、实现方式
1、浅拷贝的实现方式
1.1 Object.assign(target,source)方法
var obj = { "name":"Zs", "age":18, "grade":3, "language":["Chinese",{"name":"English"},"French"], "say":function(){console.log("hi~");} }; Object.defineProperty(obj, 'grade', { //设置obj对象的grade不可枚举 enumerable: false }); var objSon = Object.assign({},obj); objSon .name = "Ls"; objSon .language[1].name = "American"; console.log(obj,objSon);
1.2 Array.prototype.concat()方法
concat()
方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。concat
方法创建一个新的数组,它由被调用的对象中的元素组成,每个参数的顺序依次是该参数的元素(如果参数是数组)或参数本身(如果参数不是数组)。它不会递归到嵌套数组参数中。
var array1 = ['a', 'b', 'c']; var array2 = ['d', {"name":"obj"}, 'f',Symbol("id"),function three(){console.log("three~");}]; var array3 = array1.concat(array2); array1[1] = 'm'; array2[1].name = 'array2NewName'; console.log(array1,array2,array3);
var obj1 = { "name":"Zs", "age":18, "grade":3, "language":["Chinese",{"name":"English"},"French"], "say":function(){console.log("hi~");} }; Object.defineProperty(obj1, 'grade', { //设置obj对象的grade不可枚举 enumerable: false }); var obj2 = { "name":"Ls", "age":18, "grade":3, "language":["Chinese",{"name":"English"},"French"], "say":function(){console.log("hi~");} }; var objSon = Array.prototype.concat.call(obj1,obj2); objSon.name = "Wmz"; obj1.language[1].name = "American"; console.log(obj1,obj2,objSon);
1.3 Array.prototype.slice(start,end)方法
slice(
start,end)
方法返回一个新的数组对象,这一对象是一个由 start 和 end 决定的原数组的浅拷贝(包括 start 但不包括 end)。不会改变原数组。
var array1 = ['d', {"name":"obj"}, 'f',Symbol("id"),function three(){console.log("three~");},2,3]; var array2 = array1.slice(1,array1.length-2); array1[array1.length] = 'm'; array1[1].name = 'array1NewName'; console.log(array1,array2);
特点
2、深拷贝的实现方式
2.1 JSON.parse(JSON.stringify(obj))
JSON.stringify()
方法将一个 JavaScript 值(对象或者数组)转换为一个 JSON 字符串。JSON.parse()
方法用来解析JSON字符串,构造由字符串描述的JavaScript值或对象。返回值为Object
类型, 对应给定 JSON 文本的对象/值。
var obj = { "name":"Zs", "age":18, [Symbol("id")]:"ddd", "grade":3, "language":["Chinese",{"name":"English"},"French"], "say":function(){console.log("hi~");} }; Object.defineProperty(obj, 'grade', { //设置obj对象的grade不可枚举 enumerable: false }); var objSon = JSON.parse(JSON.stringify(obj)); obj.name = "Ls"; obj.language[1].name = "American"; console.log(obj,objSon);
2.2 lodash函数库
var lodashUrl = "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"; loadJS(lodashUrl,lodashLoadSuccess); //加载完js文件的回调函数:用lodash库函数中的cloneDeep方法实现深拷贝对象 function lodashLoadSuccess(){ var obj = { "name":"Zs", "age":18, [Symbol("id")]:"ddd", "grade":3, "language":["Chinese",{"name":"English"},"French"], "say":function(){console.log("hi~");} }; Object.defineProperty(obj, 'grade', { //设置obj对象的grade不可枚举 enumerable: false }); var objSon = _.cloneDeep(obj); obj.name = "Ls"; obj.language[1].name = "American"; obj..language[2] = "Japanese"; console.log(obj,objSon ); } //用js加载js文件的方法,其中url为待加载的js文件的地址,callBack为js文件加载完成时执行的回调函数 function loadJS( url, callback ){ var script = document.createElement('script'),fn = callback || function(){}; script.type = 'text/javascript'; if(script.readyState){//IE script.onreadystatechange = function(){ if( script.readyState == 'loaded' || script.readyState == 'complete' ){ script.onreadystatechange = null; fn(); } }; }else{ //其他浏览器 script.onload = function(){ fn(); }; } script.src = url; document.getElementsByTagName('head')[0].appendChild(script); }
3.3 手写递归方法
//深拷贝递归函数(只对自身的可枚举类型的属性进行拷贝) function deepClone(source){ const targetObj = source.constructor===Array?[]:{};//判断复制的目标是数组还是对象 for(let keys in source){ //遍历目标自身的和继承的可枚举属性 if(source.hasOwnProperty(keys)){//仅对自身可枚举属性进行拷贝 if(source[keys] && typeof source[keys]==='object'){//如果值是对象,就递归一下 targetObj[keys] = source[keys].constructor === Array ? [] : {}; targetObj[keys] = deepClone(source[keys]);//递归调用 }else{ //如果不是,就直接赋值 targetObj[keys] = source[keys]; } } } return targetObj; } var obj = { "name":"Zs", "age":18, [Symbol("id")]:"ddd",//设置Symbol类型键的属性 "grade":3, "language":["Chinese",{"name":"English"},"French"],//数组类型的属性 "say":function(){console.log("hi~");}//函数类型的属性 }; Object.defineProperty(obj, 'grade', { //设置obj对象的grade不可枚举 enumerable: false }); var objSon= deepClone(obj); obj.name = "Ls"; obj.language[1].name = "American"; obj.language[2] = "Japanese"; console.log(obj,objSon);
//深拷贝递归函数(可对自身的除Symbol类型的所有属性进行拷贝) function deepClone(source){ const targetObj = source.constructor===Array?[]:{};//判断复制的目标是数组还是对象 Reflect.ownKeys(source).forEach(function(keys){//遍历目标自身所有的属性 if(typeof keys != "symbol"){//源对象中非Symbol类型的属性的拷贝 if(source[keys] && typeof source[keys]==='object'){//如果属性值非空且值是对象,就需要进一步递归处理 targetObj[keys] = source[keys].constructor === Array ? [] : {}; targetObj[keys] = deepClone(source[keys]);//递归调用 }else{//对象该属性值为空或者属性值为基础类型,就直接赋值 targetObj[keys] = source[keys]; //将对应的属性的描述对象进行同步 //避免出现源对象的属性为不可枚举,深拷贝后的属性默认为可枚举属性 keysDesc = Object.getOwnPropertyDescriptor(source,keys); console.log(keys,keysDesc); for(key in keysDesc){ Object.defineProperty(targetObj, keys, {//设置obj对象的grade不可枚举 [key]: keysDesc[key] }); } console.log(Object.getOwnPropertyDescriptor(targetObj,keys)); } }else{//源对象中Symbol类型的属性处理 console.log("我是Symbol属性!"); console.log(keys); } }); return targetObj; } var obj = { "name":"Zs", "age":18, [Symbol("id")]:"ddd",//设置Symbol类型键的属性 "grade":3, "language":["Chinese",{"name":"English"},"French"],//数组类型的属性 "say":function(){console.log("hi~");}//函数类型的属性 }; Object.defineProperty(obj, 'grade', { //设置obj对象的grade不可枚举 enumerable: false }); var objSon= deepClone(obj); obj.name = "Ls"; obj.language[1].name = "American"; obj.language[2] = "Japanese"; console.log(obj,objSon);
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算