js中淺拷貝和深拷貝以及深拷貝的實現

来源:https://www.cnblogs.com/it-xiong/archive/2019/03/05/10476940.html
-Advertisement-
Play Games

前言:2019年的第一篇分享... 一、什麼是基本類型值和引用類型值?ECMAScript包括兩個不同類型的值:基本數據類型和引用數據類型。基本數據類型指的是簡單的數據段,引用數據類型指的是有多個值構成的對象。當我們把變數賦值給一個變數時,解析器首先要確認的就是這個值是基本類型值還是引用類型值。 註 ...


前言:2019年的第一篇分享...

一、什麼是基本類型值和引用類型值?
ECMAScript包括兩個不同類型的值:基本數據類型和引用數據類型。
基本數據類型指的是簡單的數據段,引用數據類型指的是有多個值構成的對象。
當我們把變數賦值給一個變數時,解析器首先要確認的就是這個值是基本類型值還是引用類型值。

註:要瞭解深拷貝和淺拷貝,首先要先理解ECMAScript中的數據類型,其中基本類型值(如undefined、null、number、string、boolean以及es6新增的Symbol), 還有一些引用類型值(如對象)。
  淺拷貝和深拷貝一般是對於引用類型值(如對象)來講的,而基本類型值,只要是複製,就一定是另開闢以存儲空間。

 

1 // 示例1(基本類型值))
2 var a = 10;
3 var b = a;
4 b = 20;
5 console.log(b); //輸出 20
6 console.log(a); //輸出 10

// 類似示例1,基本類型在拷貝的時候,b改變了,但是並不會印象到a。
1 // 示例2(引用類型值)
2 var obj_a = { a: 10, b: 20 };
3 var obj_b = obj_a;    
4 obj_b.a = 30;
5 console.log(obj_b); //輸出 { a: 30, b: 20 }
6 console.log(obj_a); //輸出 { a: 30, b: 20 }
7 
8 // 類似示例2,複雜類型在拷貝的時候,然後改變了obj_b的屬性的值,但是卻改變了obj_a的,很明顯,這個結果並不是我們想要的,其實他們還是指向同一個對象,只是展示視窗的位置不同而已。
1 // 示例3(應用類值&深拷貝)
2 var obj_a = { a: 10, b: 20, c: 30 };
3 var obj_b = { a: obj_a.a, b: obj_a.b, c: obj_a.c };
4 obj_b.a = 40;
5 console.log(obj_b); //輸出 { a: 40, b: 20, c: 30 }
6 console.log(obj_a); //輸出 { a: 10, b: 20, c: 30 }
7 
8 // 類似示例3,複雜類型在拷貝的時候,然後改變了obj_b的屬性的值,但是卻沒有改變了obj_a的,因為在拷貝的時候,其實是相當於新建了一個領地,然後遍歷舊對象的每一項的值,在新對象裡面新建每一項,然後把對應的值複製進去,他們是不同的對象,這就是所謂的深拷貝。

 

二、淺拷貝和深拷貝的原理
1.基本數據類型值( 基本數據類型值的名和值都存在棧記憶體裡面 )

如:let a = 1; 如圖:

 

  當let b = a,b複製了a,棧記憶體會另外開闢一塊地方存放b的名值,如圖:

   

 兩者互不幹涉,誰也沒有影響到誰。

2.引用數據類型值( 引用數據類型值棧記憶體裡面存值的位置則存放的是a的值在堆記憶體裡面的位置,也就是唯一堆地址 )
如:let a = [ 0, 1, 2, 3, 4 ];如圖:


當let b = a,b複製了a,b引用了a的堆地址。如圖:

  

所以這個時候,改變了b,a也會受到影響。
 
三、實現深拷貝
層級拷貝,遞歸方式(其實就是函數的自我調用)
何為層級?如,var a = [0,1,[3,4],3];
數組嵌套著數組。

 實現方法:

 // 代碼中加入判斷,當碰到數組、對象等時遞歸函數 
1
function deepClone(obj){ 2 //定義對象來判斷當前的參數是數組還是對象 3 let objClone = Array.isArray(obj)?[]:{}; 4 //如果obj存在並且為對象 5 if(obj&&typeof obj == "object"){ 6 for(let key in obj){ 7 if(obj.hasOwnProperty(key)){ 8 //如果obj的子元素為對象,那麼遞歸(層級遍歷) 9 if(obj[key]&&typeof obj[key] == "object"){ 10 objClone[key] = deepClone(obj[key]); 11 }else{ 12 //如果不是,直接賦值 13 objClone[key] = obj[key]; 14 } 15 } 16 } 17 } 18 return objClone; 19 }

 

利用 jeury.extend() 淺拷貝&深拷貝

  $.extend( [deep ], target, object1 [, objectN ] )  


註:deep表示是否深拷貝,為true為深拷貝,為false,則為淺拷貝
  target Object類型 目標對象,其他對象的成員屬性將被附加到該對象上。
  object1 objectN可選。 Object類型 第一個以及第N個被合併的對象。



1 let a = [0, 1, [2, 3], 4],
2    b = $.extend(true, [], a);
3 a[0] = 1;
4 a[2][0] = 1;
5 console.log(a, b);

通過ES6的 concat() 方法
concat()用於合併兩個或多個數組。此方法不會更改現有數組,而是返回一個新數組。


1 var a  = [1,2,3]
2 var b = a.concat();
3 b[2] =10;
4 console.log(a

上面這個情況a的值並沒有改變。

以上就是我的一些個人的理解和靖藏使用的一些深拷貝的處理方法,僅供參考。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 常見的JavaScript框架庫 1.什麼是JavaScript 框架庫? 普通JavaScript 的缺點:每種控制項的操作方式不統一,不同瀏覽器下有區別封裝庫,要編寫跨瀏覽器的程式非常麻煩。因此出現了很多對JavaScript 的。 2.常見的JavaScript 框架庫 Prototype 、Y ...
  • vue 開發過程中,保存一次就會編譯一次,如果能夠減少編譯的時間,哪怕是一丁點,也能節省不少時間。開發過程中個人編寫的源文件才會頻繁變動,而一些庫文件我們一般是不會去改動的。如果能把這些庫文件提取出來,就能減少打包體積,加快編譯速度。本文主要講述在 vue-cli3 中利用 DllPlugin 來進 ...
  • 1,在https://v3.bootcss.com/getting-started/#download下載bootstrap的壓縮包; 2,將壓縮包解壓到自己的工程文件中,會得到如下結果: 3,打開這個解壓的文件,一直點擊進去,裡面有三個文件的界面,展示如下: 4,css文件中裝的是樣式文件: 其中 ...
  • 開始我的初步認識-RequireJS能給我們帶來什麼好處? 1、實現js文件的非同步載入,避免網頁失去響應; 2、管理模塊之間的依賴性,便於代碼的編寫和維護。 3、基於AMD模塊化機制,讓前端代碼也能實現模塊化。查看《CommonJS和AMD/CMD區別詳解》。 ...
  • 我遇到了一個問題,我在已經配置babel的項目中通過require引入了一個項目目錄外層的另一個js文件,前期是可以成功轉換並打包的,但是到了後期就不行了,報錯: 這個報錯的意思是,引入的js文件中有es6的語法,所以跑項目,或者打包的時候不支持。還沒有想到babel可以如何配置,保證引入的js也自 ...
  • Web前端開發是由網頁製作演變而來的,主要由HTML、CSS、JavaScript三大要素組成。專業的Web前端開發入門知識也一定會包含這些內容,今天小編就給大家簡單介紹一下。 HTML,超文本標記語言,標準通用標記語言下的一個應用。包括“頭”部分(英語:Head)、和“主體”部分(英語:Body) ...
  • 前端開發中,總是會有這樣的需求,就是快速的寫一個腳本,或者一個簡單的demo頁面。這時,我們需要馬上可以啟動一個web服務,來支持開發。 ...
  • position:fixed; top:0; right:0; left:0; bottom:0; margin:auto; ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...