国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

詳解js中的淺拷貝與深拷貝

這篇具有很好參考價(jià)值的文章主要介紹了詳解js中的淺拷貝與深拷貝。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

1、前言

1.1 棧(stack)和堆(heap)

  • 棧(stack):由操作系統(tǒng)自動(dòng)分配釋放 ,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧;
  • 堆(heap):一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時(shí)可能由OS回收,分配方式倒是類似于鏈表

1.2 基本數(shù)據(jù)類型和引用數(shù)據(jù)類型

1.2.1 概念
  • 基本數(shù)據(jù)類型:Number、String、Boolean、Null、 Undefined、Symbol(ES6);
  • 引用數(shù)據(jù)類型:Object、Array、Function、Date、RegExp、Map、Set等。
1.2.2 區(qū)別

兩者區(qū)別:

  1. 內(nèi)存地址分配:
    1)基本數(shù)據(jù)類型:將值存儲(chǔ)在棧中 ,棧中存放的是對(duì)應(yīng)的值
    2)引用數(shù)據(jù)類型:將對(duì)應(yīng)的值存儲(chǔ)在堆中,棧中存放的是指向堆內(nèi)存的地址
  2. 賦值變量:
    1)基本數(shù)據(jù)類型:是生成相同的值,兩個(gè)對(duì)象對(duì)應(yīng)不同的地址
    2)引用數(shù)據(jù)類型:是將保存對(duì)象的內(nèi)存地址賦值給另一個(gè)變量。也就是兩個(gè)變量指向堆內(nèi)存中同一個(gè)對(duì)象
	let a = 10;
	let b = a;  // 賦值操作
	b = 100;
	console.log(a);  // 10

總結(jié):
a是基本類型,存儲(chǔ)在棧中;把a(bǔ)賦值給b,雖然兩個(gè)變量的值相等,但是兩個(gè)變量保存了兩個(gè)不同的內(nèi)存地址。

1.2.3 基本類型賦值方式

詳解js中的淺拷貝與深拷貝

1.2.4 引用類型賦值方式
	let obj1 = {}
	let obj2 = obj
	obj2.name = '李四'
	console.log(obj.name)  // 李四

理解:obj1是引用類型,將數(shù)據(jù)存放在堆內(nèi)存中,而棧中存放的是內(nèi)存地址.在obj1賦值給obj2,實(shí)際是將obj1的引用地址復(fù)制了一份給了obj2,實(shí)際上他們共同指向了同一個(gè)堆內(nèi)存對(duì)象,所以更改obj2會(huì)對(duì)obj1產(chǎn)生影響
詳解js中的淺拷貝與深拷貝

2、淺拷貝

2.1 概念

會(huì)在棧中開辟另一塊空間,并將被拷貝對(duì)象的棧內(nèi)存數(shù)據(jù)完全拷貝到該塊空間中,即基本數(shù)據(jù)類型的值會(huì)被完全拷貝,而引用類型的值則是拷貝了“指向堆內(nèi)存的地址”。

2.2 常見的淺拷貝方法

  • Object.assign()
  • 擴(kuò)展運(yùn)算符(…)
  • Array.concat()
  • Array.slice()
2.2.1 Object.assign()

object.assign 是 ES6 中 object 的一個(gè)方法,該方法可以用于JS 對(duì)象的合并等多個(gè)用途,其中一個(gè)用途就是可以進(jìn)行淺拷貝。

object.assign 的語法為:Object.assign(target, …sources)

var obj = { 
	x: 1, 
	y: 2,
	z: { 
		num: 10 
	} 
}
var newObj = {}
Object.assign(newObj, obj)
newObj.y = 3
console.log(obj)  
console.log(newObj) 

運(yùn)行結(jié)果如下:
詳解js中的淺拷貝與深拷貝

注意:

  • Object.assign()不會(huì)拷貝對(duì)象的繼承屬性;
  • Object.assign()不會(huì)拷貝對(duì)象的不可枚舉的屬性;
  • Object.assign()可以拷貝 Symbol 類型的屬性。
2.2.2 擴(kuò)展運(yùn)算符(…)

擴(kuò)展運(yùn)算符的語法為:let cloneObj = { …obj };

/* 對(duì)象的拷貝 */
const obj = {
 a: 1,
 b: {
   c: 1
 }
}
const obj2 = {
 ...obj
}
obj.a = 2

console.log(obj)
console.log(obj2); 

obj.b.c = 2

console.log(obj) 
console.log(obj2); 

/* 數(shù)組的拷貝 */
let arr = [1, 2, 3];
let newArr = [...arr]; // 跟arr.slice()是一樣的效果

運(yùn)行結(jié)果如下:
詳解js中的淺拷貝與深拷貝

注意:擴(kuò)展運(yùn)算符 和 object.assign 有同樣的缺陷,也就是實(shí)現(xiàn)的淺拷貝的功能差不多,但是如果屬性都是基本類型的值,使用擴(kuò)展運(yùn)算符進(jìn)行淺拷貝會(huì)更加方便。

2.2.3 Array.concat()
var obj1 = ["Chinese", { "name": "zs" }, "French"]
var obj2 = obj1.concat()
obj2[1].name = "ls"
obj2[2] = "China"
console.log(obj1, obj2);

運(yùn)行結(jié)果如下:
詳解js中的淺拷貝與深拷貝
注意:數(shù)組的 concat 方法其實(shí)也是淺拷貝,所以連接一個(gè)含有引用類型的數(shù)組時(shí),需要注意修改原數(shù)組中的元素的屬性,因?yàn)樗鼤?huì)影響拷貝之后連接的數(shù)組。不過 concat 只能用于數(shù)組的淺拷貝,使用場景比較局限。

2.2.4 Array.slice()

slice 的語法為:arr.slice(begin, end);

var arr = [2, 4, 6, { y: 10 }]
var newArr = arr.slice()
newArr[0] = 10
newArr[3].x = 20
newArr[3].y = 30
console.log(arr)
console.log(newArr)

運(yùn)行結(jié)果如下:
詳解js中的淺拷貝與深拷貝
注意:slice 方法也比較有局限性,因?yàn)樗鼉H僅針對(duì)數(shù)組類型。slice 方法會(huì)返回一個(gè)新的數(shù)組對(duì)象,這一對(duì)象由該方法的前兩個(gè)參數(shù)來決定原數(shù)組截取的開始和結(jié)束位置,是不會(huì)影響和改變?cè)紨?shù)組的。但是,數(shù)組元素是引用類型的話,也會(huì)影響到原始數(shù)組。

3、深拷貝

3.1 概念

深拷貝是拷貝多層,每一級(jí)別的數(shù)據(jù)都會(huì)拷貝出來。

3.2 常見的深拷貝方法

  • JSON.parse(JSON.stringify(obj))
  • 遞歸方法
  • 函數(shù)庫 lodash
3.2.1 JSON.parse(JSON.stringify(obj))

原理:用 JSON.stringify 將對(duì)象轉(zhuǎn)成 JSON 字符串,再用 JSON.parse()
把字符串解析成對(duì)象。一去一來,新的對(duì)象就產(chǎn)生了,而且對(duì)象會(huì)開辟新的棧,實(shí)現(xiàn)深拷貝。

let a = {name: '張三', age: 19, like: ['打籃球', '唱歌', '跳舞']}
let b = JSON.parse(JSON.stringify(a))
a.name = '李四'
a.like[0] = '睡覺'
console.log(a)  
console.log(b)  

運(yùn)行結(jié)果如下:
詳解js中的淺拷貝與深拷貝
但是,JSON.stringify并不是那么完美的,它也有局限性。

  • 拷貝的對(duì)象的值中如果有函數(shù)、undefined、symbol 這幾種類型,經(jīng)過 JSON.stringify 序列化之后的字符串中這個(gè)鍵值對(duì)會(huì)消失;
  • 拷貝 Date 引用類型會(huì)變成字符串;
  • 無法拷貝不可枚舉的屬性;
  • 無法拷貝對(duì)象的原型鏈;
  • 拷貝 RegExp 引用類型會(huì)變成空對(duì)象;
  • 對(duì)象中含有 NaN、Infinity 以及 -Infinity,JSON 序列化的結(jié)果會(huì)變成 null;
  • 無法拷貝對(duì)象的循環(huán)應(yīng)用,即對(duì)象成環(huán) (obj[key] = obj)。
let obj = {
	 func: function () { alert(1) },
	 obj: { a: 1 },
	 arr: [1, 2, 3],
	 und: undefined,
	 reg: /123/,
	 date: new Date(0),
	 NaN: NaN,
	 infinity: Infinity,
	 sym: Symbol('1')
}

Object.defineProperty(obj, 'innumerable', {
	enumerable: false,
	value: 'innumerable'
});

console.log('obj', obj); // { NaN: NaN , arr: (3) [1, 2, 3] ,date: Thu Jan 01 1970 08:00:00 GMT+0800 (中國標(biāo)準(zhǔn)時(shí)間) {}, func: ?(), infinity: Infinity , obj: { a: 1 } , reg: /123/, sym: Symbol(1), und: undefined, innumerable: "innumerable" }

const str = JSON.stringify(obj);

const obj1 = JSON.parse(str);

console.log('obj1', obj1); // { NaN: null, arr: (3) [1, 2, 3], date: "1970-01-01T00:00:00.000Z", infinity: null, obj: {a: 1}, reg: {} }
3.2.2 遞歸
 function deepCopyTwo(obj) {
    let objClone = Array.isArray(obj) ? [] : {};
     if (obj && typeof obj == 'object') {
         for (const key in obj) {
             //判斷obj子元素是否為對(duì)象,如果是,遞歸復(fù)制
             if (obj[key] && typeof obj[key] === "object") {
                 objClone[key] = deepCopyTwo(obj[key]);
             } else {
                 //如果不是,簡單復(fù)制
                 objClone[key] = obj[key];
             }
         }
     }	
     return objClone;
 }
3.2.2 函數(shù)庫lodash

lodash是一個(gè)著名的javascript原生庫,不需要引入其他第三方依賴。是一個(gè)意在提高開發(fā)者效率,提高JS原生方法性能的JS庫。簡單的說就是,很多方法lodash已經(jīng)幫你寫好了,直接調(diào)用就行,不用自己費(fèi)盡心思去寫了,而且可以統(tǒng)一方法的一致性。Lodash使用了一個(gè)簡單的_ 符號(hào),就像Jquery的 $ 一樣,十分簡潔。lodash函數(shù)庫提供 _.cloneDeep用來做深拷貝。文章來源地址http://www.zghlxwxcb.cn/news/detail-474252.html

	let _ = require('lodash');
	let obj = {
	    a:1,
	    b:{f:{g:1}},
	    c:[1,2,3]
	};
	let newObj = _cloneDeep(obj);
	console.log(obj.b.f === newObj.b.f); //true

4、總結(jié)

  • 淺拷貝就是只拷貝基礎(chǔ)數(shù)據(jù)類型的數(shù)據(jù),并且數(shù)據(jù)只有單一的一層,而深拷貝用于拷貝具有復(fù)雜的數(shù)據(jù)類型的數(shù)據(jù)

5、應(yīng)用場景

  • 淺拷貝主要用于你需要拷貝的對(duì)象的數(shù)據(jù)結(jié)構(gòu)只有基礎(chǔ)數(shù)據(jù)類型,并且你不想改變?cè)瓟?shù)據(jù)類型或者需要對(duì)比操作前后的數(shù)據(jù)。
  • 深拷貝主要用于你想操作該數(shù)據(jù),但是又不想影響到原數(shù)據(jù)的時(shí)候,就可以進(jìn)行深拷貝。

到了這里,關(guān)于詳解js中的淺拷貝與深拷貝的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • [開發(fā)語言][c++][python]:C++與Python中的賦值、淺拷貝與深拷貝

    [開發(fā)語言][c++][python]:C++與Python中的賦值、淺拷貝與深拷貝

    寫在前面 :Python和C++中的賦值與深淺拷貝,由于其各自語言特性的問題,在概念和實(shí)現(xiàn)上稍微有點(diǎn)差異,本文將這C++和Python中的拷貝與賦值放到一起,希望通過對(duì)比學(xué)習(xí)兩語言實(shí)現(xiàn)上的異同點(diǎn),加深對(duì)概念的理解。 C++中所謂的 淺拷貝 就是由(系統(tǒng)默認(rèn)的) 拷貝構(gòu)造函數(shù)對(duì)

    2024年02月02日
    瀏覽(28)
  • Python中淺拷貝與深拷貝

    在本文中,將介紹如何在Python 3中復(fù)制或“克隆”對(duì)象,以及所涉及的一些注意事項(xiàng)。 注:本教程是用Python 3編寫的,但是在復(fù)制對(duì)象時(shí),Python 2和3并沒有什么區(qū)別。當(dāng)有不同時(shí),會(huì)在文中指出。 讓我們首先看看如何復(fù)制Python的內(nèi)置集合。Python內(nèi)置的集合是可變的,如列表、

    2024年02月02日
    瀏覽(34)
  • python-淺拷貝(copy)與深拷貝(deepcopy)

    python-淺拷貝(copy)與深拷貝(deepcopy)

    目錄 一、前言: 二、深拷貝與淺拷貝的異同: ? ? ? ? 1.相同點(diǎn):? ? ? ? ????????2.不同點(diǎn): ????????3.形象說明: ? ? ? ? 注意: 三、淺拷貝: ?3.1.1淺拷貝示意圖: 3.1.2示意圖說明 ? ? ? ? 1.對(duì)象與子對(duì)象(元素)的關(guān)系: ????????2.對(duì)象: ????????3.元

    2024年02月11日
    瀏覽(16)
  • vue~對(duì)象的淺拷貝

    當(dāng)我們想要復(fù)制一段數(shù)據(jù)的時(shí)候嗎,我們就會(huì)用到拷貝;拷貝數(shù)據(jù)又分為了淺拷貝和深拷貝,淺拷貝指復(fù)制對(duì)象或數(shù)組的頂層結(jié)構(gòu),如果對(duì)象或數(shù)組中有引用類型的屬性值,復(fù)制的是引用(地址)而非值;而深拷貝則是遞歸復(fù)制完整的對(duì)象或數(shù)組,包括嵌套的子對(duì)象或子數(shù)組

    2024年02月09日
    瀏覽(13)
  • 理解C#中對(duì)象的淺拷貝和深拷貝

    本文章主要介紹C#中對(duì)象的拷貝,其中包括淺拷貝和深拷貝,以及淺拷貝和深拷貝的實(shí)現(xiàn)方式,不同的實(shí)現(xiàn)方式之間的性能對(duì)比。 ? 淺拷貝是指將對(duì)象中的數(shù)值類型的字段拷貝到新的對(duì)象中,而對(duì)象中的引用型字段則指復(fù)制它的一個(gè)引用到目標(biāo)對(duì)象。如果改變目標(biāo)對(duì)象中引用

    2024年02月08日
    瀏覽(22)
  • 5個(gè)常見的前端手寫功能:淺拷貝與深拷貝、函數(shù)柯里化、數(shù)組扁平化、數(shù)組去重、手寫類型判斷函數(shù)

    5個(gè)常見的前端手寫功能:淺拷貝與深拷貝、函數(shù)柯里化、數(shù)組扁平化、數(shù)組去重、手寫類型判斷函數(shù)

    淺拷貝 淺拷貝是創(chuàng)建一個(gè)新對(duì)象,這個(gè)對(duì)象有著原始對(duì)象屬性值的一份精確拷貝。如果屬性是基本類型,拷貝的就是基本類型的值,如果屬性是引用類型,拷貝的就是內(nèi)存地址,所以如果其中一個(gè)對(duì)象改變了這個(gè)地址,就會(huì)影響到另一個(gè)對(duì)象。 測試結(jié)果: 深拷貝 深拷貝是將

    2024年04月26日
    瀏覽(23)
  • 前端 js 棧內(nèi)存和堆內(nèi)存 基本數(shù)據(jù)類型和復(fù)雜數(shù)據(jù)類型的區(qū)別?

    前端 js 棧內(nèi)存和堆內(nèi)存 基本數(shù)據(jù)類型和復(fù)雜數(shù)據(jù)類型的區(qū)別?

    先了解一下JavaScript 數(shù)據(jù)類型有哪些? javaScript 中有8種基本的數(shù)據(jù)類型:7種為基本數(shù)據(jù)類型,而Object 為復(fù)雜數(shù)據(jù)類型 基本數(shù)據(jù)類型(原始數(shù)據(jù)類型): number 用于任何類型的數(shù)字 bigint 用于任意長度的整數(shù)。 string 用于字符串 boolean :布爾值 用于 true 和 false。 null 用于未知的

    2024年02月11日
    瀏覽(21)
  • js深拷貝、淺拷貝

    1.淺拷貝 這個(gè)很簡單,淺拷貝拷貝的就是地址,其中一個(gè)修改另一個(gè)也會(huì)改變。 淺拷貝拷貝的是地址,只會(huì)拷貝最外層的對(duì)象(即只會(huì)拷貝一層) 拷貝對(duì)象:Object.assign(os,obj) || const os={…obj} 拷貝數(shù)組:Array.prototype.concat() || […arr] 存在問題:對(duì)象內(nèi)還有對(duì)象的時(shí)候進(jìn)修改內(nèi)部對(duì)象的屬

    2024年02月12日
    瀏覽(12)
  • js中的promise詳解

    ? ? ? ?Promise是異步編程的一種解決方案,可以替代傳統(tǒng)的解決方案--回調(diào)函數(shù)和事件。ES6統(tǒng)一了用法,并原生提供了Promise對(duì)象。作為對(duì)象,Promise有以下兩個(gè)特點(diǎn): (1)對(duì)象的狀態(tài)不受外界影響。 (2)一旦狀態(tài)改變了就不會(huì)再變,也就是說任何時(shí)候Promise都只有一種狀態(tài)。 ? ?

    2024年02月02日
    瀏覽(16)
  • JS的深拷貝和淺拷貝

    JS的深拷貝和淺拷貝

    ?本文作者是360奇舞團(tuán)開發(fā)工程師 在討論深拷貝和淺拷貝之前,先來了解下Js基本數(shù)據(jù)和引用數(shù)據(jù)類型的存儲(chǔ)問題 基本數(shù)據(jù)類型:Number String Boolean Undefined Symbol Null 引用類型 :Object,function,Array等 基本數(shù)據(jù)類型的值存放在棧中,在棧中存放的是對(duì)應(yīng)的值;引用類型對(duì)應(yīng)的值存

    2024年02月09日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包