看看你知道的「淺拷貝」是對的嗎

2021-03-02 妙味前端

關於本篇文章的起源是一位大佬在面試的時候,詢問應聘者關於淺拷貝的知識後,在應聘者的回答中,筆者發現有好一部分人對淺拷貝都是錯誤的,故有了此篇內容。

1. 還原現場

大佬:「如何複製一個對象?」

她: 「複製對象有深拷貝和淺拷貝...」

大佬:」說一下這兩者之間的區別「

她: 」我給你寫一段淺拷貝的代碼「

var a = { x: 1 };var b = a;

大佬:」回去等通知吧 ~.~「

2. 一探究竟

剛開始看到上面應聘者的例子的時候,其實我也認為應聘者寫的是對的,因為在我的記憶裡,對象的淺拷貝就是兩個變量存儲的值是相同的堆地址,而上面應聘者寫的 a 和 b 符合這個條件,但是大佬提出異議後,便立刻去google了一把,發現Javascript的淺拷貝居然沒有官方定義(有人找到的話麻煩評論區貼一個地址,非常感謝)。

於是我去MDN(https://developer.mozilla.org)上查了一下shallow copy的關鍵字,也沒有關於shallow copy的準確定義,這也難怪部分人對於淺拷貝會有不同的認識。

第一種定義:一個新的對象直接拷貝已存在的對象的引用,即淺拷貝。

第二種定義:一個新的對象直接拷貝已存在的對象的對象屬性的引用,即淺拷貝。

第一種和第二種的差異即是,對象本身引入與對象的對象屬性的引入,因為我沒有找到標準的關於淺拷貝的官方定義,所以對於這兩種方式便開始思考想辦法去驗證。

在前面MDN中搜索shallow copy時,雖然沒有找到它的定義,但是找了一個一些其他的內容。

Array.prototype.slice()屬於淺拷貝,那我們來驗證一下Array.prototype.slice()返回的新數組對象和老的數組對象之間究竟符合那種關係。

var a = [ 1, 3, 5, { x: 1 } ];var b = Array.prototype.slice.call(a);b[0] = 2;console.log(a); console.log(b); 

很明顯,屬於淺拷貝的a和b並不是第一種定義所描述的,如果a和b是相同的引用對象,當b[0]改變時a[0]應當是跟著改變。

var a = [ 1, 3, 5, { x: 1 } ];var b = Array.prototype.slice.call(a);b[3].x = 2;console.log(a); console.log(b); 

通過上面的代碼既可以看出,淺拷貝的正確定義是第二種,只拷貝已存在對象的對象屬性的引用,其餘非對象屬性是佔用新的內存空間,並非與原對象共享。

3. 歸納總結

通過上面的內容,理清楚了淺拷貝的定義,而隨之引出的」深拷貝「又是怎樣的?和」淺拷貝「有什麼關係?在下面總結一番。

淺拷貝:新的對象複製已有對象中非對象屬性的值和對象屬性的引用。

簡單實現一個淺拷貝函數:

var a = [ 1, 3, 5, { x: 1 } ];function copy(a){  let b = Array.isArray(a) ? [] : {};  for (let i in a) {    b[i] = a[i];  }  return b;}

像常用的數組方法slice和對象方法Object.assign都屬於淺拷貝。

深拷貝:遍歷一個對象中所有的屬性的值及對象屬性中的屬性值,不論是嵌套了幾層,要完成所有對象屬性的遞歸後,賦值給一個新的對象。

var a = { x: 1, y: { x: 1 } };function copy(data) {var b={};  if (typeof data === 'number') {    return data  }  for (var i in data) {        if (data.hasOwnProperty(i)) {      b[i] = copy(data[i]);    }  }  return b;}

也可以使用快捷的深拷貝方式,完成對象複製,但是這種方式要求所要複製的對象的屬性值非函數。

var b = JSON.parse(JSON.stringify(a));

如上內容均為自己總結,難免會有錯誤或者認識偏差,如有問題,希望大家留言指正,以免誤人。


如果覺得本文有幫助,歡迎多多轉發點讚,推薦給更多的小夥伴喲

更多前端系統學習視頻教程,點擊這裡獲取哦:https://study.miaov.com/study

好消息~好消息~即日起新註冊的用戶,可享受新人「VIP視頻」禮包哦,註冊後記得添加微信客服:miaov_xy 來獲取哦



相關焦點

  • 前端面試-深拷貝和淺拷貝
    面試題目:如何實現對一個數組或對象的淺拷貝和深拷貝?WTF,複製還分兩種,第一次遇到這種問題的時候很是無語呢,先來看看一般的答案的理解。淺拷貝是只拷貝一層,深層次的對象級別就只拷貝引用。 深拷貝是拷貝多層,每一級別的數據都拷貝出來。
  • 5 張圖徹底理解 Python 中的淺拷貝與深拷貝
    Python 開發崗,面試官如果對基礎比較看重的話,那麼很可能會問你這樣的問題「談談你對 Python 中的淺拷貝和深拷貝的理解?」若平時你在開發中過度使用 deepcopy,以至於忘記了淺拷貝(shallow copy)和深拷貝(deep copy)的區別,那很可能要栽大跟頭了。本文轉載一篇小吉大佬的文章,幫助大家更好的理解深拷貝和淺拷貝的區別。
  • Python深拷貝和淺拷貝詳解
    Python淺拷貝常見的淺拷貝的方法,是使用數據類型本身的構造器,比如下面兩個例子:list1 = [1, 2, 3]list2 = list(list1)print(list2)print("list1==list2 ?",list1==list2)print("list1 is list2 ?"
  • 一文讀懂 javascript 深拷貝與淺拷貝
    讀完本文,希望你能明白:淺拷貝與深拷貝淺拷貝是創建一個新對象,這個對象有著原始對象屬性值的一份精確拷貝。如果屬性是基本類型,拷貝的就是基本類型的值,如果屬性是引用類型,拷貝的就是內存地址 ,所以如果其中一個對象改變了這個地址,就會影響到另一個對象。
  • 面試題-python 淺拷貝和深拷貝(copy模塊)
    前言面試的時候經常會問到深拷貝和淺拷貝,那麼python的深拷貝和淺拷貝有什麼區別呢?id函數獲取內存地址,我們說的深拷貝和淺拷貝是針對可變對象:list、dict 和 set集合copy模塊python 中的深拷貝和淺拷貝使用 copy 模塊淺拷貝 A shallow copy constructs a new compound object and then (to the extent possible) inserts references into
  • 深拷貝和淺拷貝之list、dataframe
    python list:b = a是淺拷貝,b = list(a)和b = copy.cpoy(a)是深拷貝。淺拷貝,a和b指向的是一個地址。當b改變後,a也會改變。深拷貝,a和b指向的是兩個地址,當b改變後,a不受影響。
  • 低門檻徹底理解JavaScript中的深拷貝和淺拷貝
    在說深拷貝與淺拷貝前,我們先看兩個簡單的案例:按照常規思維,obj1應該和num1一樣,不會因為另外一個值的改變而改變,而這裡的obj1 卻隨著obj2的改變而改變了。同樣是變量,為什麼表現不一樣呢?案例2中的賦值就是典型的淺拷貝,並且深拷貝與淺拷貝的概念只存在於引用類型。深拷貝與淺拷貝既然已經知道了深拷貝與淺拷貝的來由,那麼該如何實現深拷貝?
  • JavaScript系列--如何優雅簡單的實現深拷貝和淺拷貝
    優雅簡單的實現深拷貝和淺拷貝淺析JavaScript解析賦值、淺拷貝和深拷貝的區別:裡面介紹了解析賦值,淺拷貝,深拷貝的原理和實現。二、數組淺拷貝如果是數組,可以使用數組的一些方法實現:slice(),concat()返回一個新數組的特性實現拷貝。
  • C++之拷貝構造函數的淺copy和深copy
    一、深拷貝和淺拷貝構造函數總結:1、兩個特殊的構造函數:(1)無參構造函數::(1)淺拷貝拷貝後對象的物理狀態相同(2)深拷貝拷貝後對象的邏輯狀態相同(3)編譯器提供的拷貝構造函數隻進行淺拷貝代碼版本一:#include <stdio.h>#include <string>class Test{
  • Java 拷貝,你能說出個 123 麼?
    作者 | sowhat1412 責編 | 張文頭圖 | CSDN 下載自視覺中國本文主要講解:對象創建方式、Java中的深拷貝和淺拷貝。本次講解的是 Java 的深拷貝和淺拷貝,其實現方式正是通過調用 Object 類的 clone() 方法來完成。
  • 深淺拷貝知多少?
    這種情況是否也會在你的項目中出現?如果沒出現的,我來分享下,避免後續再有此情況發生。下面就 針對在什麼情況下賦值會改變原有對象的值進行進一步說明。首先帶你了解下數據類型和基礎概念。 JS數據類型JS數據類型分為:基本數據類型和對象數據類型。基本數據類型:直接存儲在棧(stack)中的數據。
  • JavaScript的深拷貝實現
    在實際開發當中,我們經常會遇到要對對象進行深拷貝的情況。而且深拷貝這個問題在面試過程中也經常會遇到,下面就對本人在學習過程中的收穫,做以簡單的總結。什麼是淺拷貝,什麼是深拷貝?什麼是淺拷貝關於淺拷貝的概念,我在網上看到一種說法,直接上代碼。
  • 圖解 Python 中深淺拷貝(copy)
    為了生成這個副本,就產生了拷貝。今天就說一下Python中的深淺拷貝問題。淺copy其實列表是一個一個的槽位,每個槽位存儲的是該對象的內存地址l1 = [1, 2, 3, [22, 33]]l2 = l1.copy()l1.append(666)print(l1) print(l2)
  • 什麼是Java深淺拷貝?
    拷貝與Java內存結構息息相關,搞懂Java深淺拷貝是很必要的!在對象的拷貝中,很多初學者可能搞不清到底是拷貝了引用還是拷貝了對象。在拷貝中這裡就分為引用拷貝、淺拷貝、深拷貝進行講述。引用拷貝引用拷貝會生成一個新的對象引用地址,但是兩個最終指向依然是同一個對象。如何更好的理解引用拷貝呢?
  • 深拷貝的終極探索(90%的人都不了解)
    ,由淺入深,環環相扣,總共涉及4種深拷貝方式,每種方式都有自己的特點和個性深拷貝 VS 淺拷貝再開始之前需要先給同學科普下什麼是深拷貝,和深拷貝有關係的另個一術語是淺拷貝又是什麼意思呢?a的數據,根據拷貝的層級不同可以分為淺拷貝和深拷貝,淺拷貝就是只進行一層拷貝,深拷貝就是無限層級拷貝var a1 = {b: {c: {}};var a2 = shallowClone(a1); // 淺拷貝a2.b.c === a1.b.c // truevar a3 = clone(a1); // 深拷貝a3.b.c === a1.b.c // false淺拷貝的實現非常簡單
  • 一篇文章讀懂Python賦值與拷貝
    拷貝又分為淺拷貝和深拷貝。>>> s == sc == sdc True>>> s is sc False>>> s is sdcFalse那麼淺拷貝(shallow copy)與深拷貝(deep copy)有什麼區別呢?
  • 面試題:如何實現一個深拷貝
    (給前端大全加星標,提升前端技能)作者:木易楊 (本文來自作者投稿)引言上篇文章詳細介紹了淺拷貝 Object.assign
  • 今天就讓你十分鐘玩懂-零拷貝
    微信公眾號:moon聊技術本文約3500字,完整閱讀大概會花費你「10分鐘」左右的時間[如果你覺得文章對你有幫助,歡迎關注,點讚,轉發]前言'零拷貝'這個詞大家應該不陌生了,也算是大廠面試中的一個高頻考點,玩過 NETTY 的朋友應該對此相當熟悉了,NETTY 的
  • Pandas和Numpy的視圖和拷貝
    在Numpy和Pandas中,有兩個重要概念,容易混淆,一個是淺拷貝,也稱為視圖,另外一個是深拷貝,或者就稱為拷貝。如果操作不當,Pandas會爆出SettingWithCopyWarning的異常。本文我將就視圖和拷貝問題,結合異常進行總結。
  • 阿里Java開發規約為什麼不建議使用Apache BeanUtils拷貝對象?
    前言做 JAVA 開發的同學都知道,在 JAVA 世界中萬事萬物皆為對象。是我們在實際開發中,經常會遇到將一個對象實例拷貝轉換為另一個對象實例的情況:對兩個對象的屬性進行淺(深)度複製。在具體介紹 BeanUtils 工具以前,先介紹一個有關拷貝的基礎知識。其實所有的 BeanUtils本質上就是對象拷貝工具,通常對象拷貝分為:深拷貝和淺拷貝,接下來做詳細解釋。