c++对那些类型的数据不能使用引用_基于js数据类型浅谈deepClone
談到deepClone,對于一些剛入手前端的小伙伴可能會發現一些問題,舉個簡單的例子:
let a = {apple: 1} let b = a b.apple = 2 console.log(a.apple) // 2我們會發現,修改b的時候,a也被修改了,這種情況下在我們一般的項目中,不是我們想要的結果,如何保持a不變呢,這時候就會需要深拷貝這個東西。在這之前呢,有個東西你必須先熟悉,那就是js的數據類型,這對了解深拷貝是至關重要的。
一、數據類型
在JS中,數據類型分為基本數據類型和引用數據類型兩種,分別存在內存中的棧和堆中。
- 棧(stack)中主要存放一些基本類型的變量和對象的引用(包含引用類型的值的變量并不是對象本身,而是一個指向該對象的指針,復制該對象的話,實際上是復制該對象的指針),其優勢是存取速度比堆要快,并且棧內的數據可以共享,但缺點是存在棧中的數據大小與生存期必須是確定的,缺乏靈活性。
- 堆(heap)用于復雜數據類型(引用類型)分配空間,例如數組對象、object對象;它是運行時動態分配內存的,因此存取速度較慢。
1.基本數據類型
基本數據類型的值直接存儲在棧內存中;棧有一個很重要的特殊性,就是存在棧中的數據可以共享。例如下面的代碼定義兩個變量,變量的值都是數字類型。
var a=3; var b=3;JavaScript將首先處理 var a=3;,會在棧中創建一個變量為a引用,然后查找棧中是否有3這個值,如果沒有找到,就將3存放進來,然后將a指向3。接著處理 var b=3;,在創建為b的引用變量后,查找棧中是否有3這個值,因為此時棧中已經存在了3,便將b直接指向3。這樣,就出現了a與b同時指向3的情況。此時,如果再令a=4,那么JavaScript解釋引擎會重新搜查棧中是否有4這個值,如果有,則將4存放進來,并令a指向4;如果已經有了,則直接將a指向這個地址。因此a值的改變不會影響到b的值。
2.引用數據類型
引用類型在棧內存中僅僅存儲了一個引用,而真正的數據存儲在堆內存中;
具體的例子,在開頭的例子中,就屬于引用數據類型的現象。對象是引用類型的值,對于引用類型來說,我們將 a 賦予 b 的時候,我們其實僅僅只是將 a 存儲在棧堆中的的引用賦予了 b ,而兩個對象此時指向的是在堆內存中的同一個數據,所以當我們修改任意一個值的時候,修改的都是堆內存中的數據,而不是引用,所以只要修改了,同樣引用的對象的值也自然而然的發生了改變。
這種情況,就是一個淺拷貝,就是只拷貝對象的引用,而不深層次的拷貝對象的值,多個對象指向堆內存中的同一對象,任何一個修改都會使得所有對象的值修改,因為它們公用一條數據。
二、深拷貝
深拷貝作用在引用類型上,例如:Object,Array;深拷貝不會拷貝引用類型的引用,而是將引用類型的值全部拷貝一份,形成一個新的引用類型。
下面介紹幾種簡易的方式:
此方法不可以拷貝 undefined , function, RegExp 等等類型的。
此方法不可以用于多層嵌套的對象。
我們可以遞歸去復制所有層級屬性,以實現深拷貝:
function deepClone(obj) {//判斷拷貝的要進行深拷貝的是數組還是對象,是數組的話進行數組拷貝,對象的話進行對象拷貝const toString = Object.prototype.toStringtoString.call(o) === '[object Array]' ? c = c || [] : c = c || {}for (const i in o) {if (typeof o[i] === 'object' && o[i]!==null) {// 要考慮深復制問題了if (Array.isArray(o[i])) {// 這是數組c[i] = []} else {// 這是對象c[i] = {}}deepClone(o[i], c[i])} else {c[i] = o[i]}}return c }總結
以上是生活随笔為你收集整理的c++对那些类型的数据不能使用引用_基于js数据类型浅谈deepClone的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: logback修改日志内容_记一次Log
- 下一篇: android 增删改查 源码_学生信息