1. 程式人生 > >js中實現深淺拷貝

js中實現深淺拷貝

值型別和引用型別

說起深淺拷貝,我覺得需要理清楚 值型別引用型別

值型別

所謂 值型別 就是 undefinednullnumberstringboolean 等五種基本資料型別, 應該還有一個Symbol型別。

值型別的資料儲存在棧記憶體中

值型別 中修改值相當於重新在棧記憶體中開闢了一個新的儲存空間,類似於:
這裡寫圖片描述
用程式碼來解釋就是:

var num1 = 5
var num2 = num1

值型別的值不可改變

javascript中的原始值(undefined、null、布林值、數字和字串)與物件(包括陣列和函式)有著根本區別。原始值是不可更改的:任何方法都無法更改(或“突變”)一個原始值。對數字和布林值來說顯然如此 —— 改變數字的值本身就說不通,而對字串來說就不那麼明顯了,因為字串看起來像由字元組成的陣列,我們期望可以通過指定索引來假改字串中的字元。實際上,javascript 是禁止這樣做的。字串中所有的方法看上去返回了一個修改後的字串,實際上返回的是一個新的字串值。

var str = 'abc'
str[0] = 'd'
console.log(str)  // 'abc'

值型別的比較是對值的比較
值型別的比較是值的比較,只要它們的值相等就認為他們是相等的

var a = 1;
var b = 1;
console.log(a === b);//true

引用型別

引用型別的資料存放在堆記憶體中
引用型別的值存放在堆記憶體中,變數儲存的是一個存放在棧記憶體,指向堆記憶體的指標。

var person1 = {name:'jozo'};
var person2 = {name:'xiaom'};
var person3 = {name:'xiaoq'
};

這裡寫圖片描述

引用型別的值可以改變
引用型別是可以直接改變其值的

 var a = [1,2,3];
 a[1] = 5;
 console.log(a[1]); // 5

引用型別的比較是引用的比較
所以每次我們對 js 中的引用型別進行操作的時候,都是操作其物件的引用(儲存在棧記憶體中的指標),所以比較兩個引用型別,是看其的引用是否指向同一個物件。

var a = [1,2,3];
var b = [1,2,3];
console.log(a === b); // false

var a = [1, 2, 3]
var b = a
console.log(a === b)  // true

傳值與傳址

瞭解了基本資料型別與引用型別的區別之後,我們就應該能明白傳值與傳址的區別了。
在我們進行賦值操作的時候,基本資料型別的賦值(=)是在記憶體中新開闢一段棧記憶體,然後再把再將值賦值到新的棧中

var a = 10;
var b = a;

a ++ ;
console.log(a); // 11
console.log(b); // 10

這裡寫圖片描述

所以說,基本型別的賦值的兩個變數是兩個獨立相互不影響的變數。

但是引用型別的賦值是傳址。只是改變指標的指向,例如,也就是說引用型別的賦值是物件儲存在棧中的地址的賦值,這樣的話兩個變數就指向同一個物件,因此兩者之間操作互相有影響。

var a = {}; // a儲存了一個空物件的例項
var b = a;  // a和b都指向了這個空物件

a.name = 'jozo';
console.log(a.name); // 'jozo'
console.log(b.name); // 'jozo'

b.age = 22;
console.log(b.age);// 22
console.log(a.age);// 22

console.log(a == b);// true

這裡寫圖片描述

淺拷貝

這裡寫圖片描述

實現

function shallowCopy (src) {
    let  new = {}
    for (let i in src) {
        if (src.hasOwnProperty(i)) {
            new[i] = src[i]
        }
    }
    return new
}

深拷貝

一種騷操作是利用JSON.parse 和 JSON.stringify

var a = {
    name: 'SpawN',
    age: 28
}

var b = JSON.parse(JSON.stringify(a))
b.name = 'Johnny.R'

console.log(a.name)  // 'SpawN'

另外一種是科班操作,也就是常規操作,就是利用遞迴,來遍歷目標物件下的所有屬性

function deepCopy(obj) {
    if (typeof obj !== 'object') return
    // 初始化
    var newObj = obj instanceof Array ? [] : {}
    for (let k in obj) {
        if (obj.hasOweProperty(k)) {
            newObj[k] = typeof obj[k] === 'object' ? agruments.callee(obj[k]) : obj[k]
        }
    }
    return newObj
}

這裡僅僅是實現了基本的深拷貝,對一些邊界並沒有進行妥善的處理。基本思路就是通過for in 迴圈,當值為物件的時候,再遞迴進行for in迴圈。

相關推薦

js實現深淺拷貝

值型別和引用型別 說起深淺拷貝,我覺得需要理清楚 值型別 和 引用型別 值型別 所謂 值型別 就是 undefined,null,number, string ,boolean 等五種基本資料型別, 應該還有一個Symbol型別。 值型別的資料儲存在

js深淺拷貝理解

淺拷貝,通俗理解就是拷貝一層,例如{a:1,b:{c:1,d:2}},那麼拷貝的是a,b指向的記憶體的位置;由於b指向的是一個物件的引用,那麼,我對原來物件中的c屬性進行修改,也會影響到新物件屬性的值;但是修改原來物件中a的值,就不會影響後新物件a的值; 那麼如何實現淺拷貝呢? func

js深淺拷貝

js中的深拷貝與淺拷貝 深拷貝: 如果拷貝的時候,將當前物件的資料的引用結構都拷貝一份,即深拷貝,資料在記憶體中獨立存在。 淺拷貝: 若拷貝的時候,只針對當前物件的屬性地址的拷貝,即淺拷貝。 拷貝: 複製一份,指將物件資料複製一份。 *注意

js的深拷貝和淺拷貝

所有 object 簡單的 col images new color 其他 java 深復制和淺復制只針對像 Object, Array 這樣的復雜對象的。簡單來說,淺復制只復制一層對象的屬性,而深復制則遞歸復制了所有層級。 深淺拷貝 的主要區別就是:復制的是引用(地址)還

JS實現JSON對象和JSON字符串之間的相互轉換

獲取 bsp com .com ins 對象 ie7 strong line 對於主流的瀏覽器(比如:firefox,chrome,opera,safari,ie8+),瀏覽器自己提供了JSON對象,其中的parse和stringify方法實現了JSON對象和JSON字符串

js實現高德地圖坐標經緯度轉百度地圖坐標

math.sqrt pan poi 結果 mat blog 筆記 百度 說明 1 function tobdMap(x, y) { 2 var x_pi = 3.14159265358979324 * 3000.0 / 180.0; 3

js實現繼承的不同方式以及其缺點

但是 scrip UC .proto 就是 圖片 問題 inf 引用 1.利用call和apply,借助構造函數 fucntion P(){ this.name = "P"; } fucntion C1(){ P.call(this); }

js的深拷貝與淺拷貝

nbsp 中一 局限性 深拷貝與淺拷貝 ext bsp post body extend 對於字符串類型,淺拷貝是對值的拷貝,對於對象來說,淺拷貝是對對象地址的拷貝,並沒有開辟新的棧,也就是拷貝的結果是兩個對象指向同一個地址,修改其中一個對象的屬性,則另一個對象的屬性也會改

[記錄] JavaScript 深淺拷貝(克隆)

ray 方式 pro 是否 span div ext 引用 針對 淺拷貝和深拷貝針對的是Object、Array這樣復雜的引用類型數據 簡單說:淺拷貝只復制一層的屬性,而深拷貝則遞歸復制所有層級的屬性 一、淺拷貝 1 function clone(origin

淺談關於java深淺拷貝

long private 創建 .com ktr nal ride 相同 cto 一.淺拷貝(shallow copy) 1.如何實現淺拷貝? Object類 是所有類的直接或間接父類,Object中存在clone方法,如下 protected native O

Node.js使用pipe拷貝大文件不能完全拷貝的解決辦法

ads 沒有 str pat some pipe reads 大文件 close 原來的代碼如下: var readable = fs.createReadStream( filepath ); var writable = fs.createWriteStream( ou

js實現跨域的幾種方法

js中幾種實用的跨域方法原理詳解 這裡說的js跨域是指通過js在不同的域之間進行資料傳輸或通訊,比如用ajax向一個不同的域請求資料,或者通過js獲取頁面中不同域的框架中(iframe)的資料。只要協議、域名、埠有任何一個不同,都被當作是不同的域。 下表給出了相對http://sto

angular.js和vue.js實現函數去抖(debounce)

搜索輸入框 sea class 方案 get clas 電路 dia ive 問題描述 搜索輸入框中,只當用戶停止輸入後,才進行後續的操作,比如發起Http請求等。 學過電子電路的同學應該知道按鍵防抖。原理是一樣的:就是說當調用動作n毫秒後,才會執行該動作,若在這n毫秒內又

JS的淺拷貝和深拷貝

拷貝 結果 如果 string typeof aso clone return isarray //淺拷貝 var o1 = { a: 10, b: 20, c: 30 }; var o2 = o1; o2.a = 100; console.log(o1);

JS實現陣列取最大值

情景: 有一個如下陣列: var classify=["5","47","98","12","165"]; 我現在要求取出這個數組裡面的最大值。 完整程式碼: function ceshi(){ var classify=["5","47","98","12","165

Java支援深淺拷貝的第三方庫

深拷貝 Apache旗下的Commons-Lang3包有一個序列化的工具SerializationUtils,可以做深拷貝。 當然前提是你的類實現了序列化介面。 Java Deep Cloning Library是我覺得最好用的一個。它的深拷貝通過反射實現,適合用於你 不能控制的第三方類或者沒有實現序

JS--變數及深淺拷貝

JS變數分為基本型別和引用型別     基本型別資料包括Number, String, Boolean, Null, Undefined五種型別; 引用資料型別包括Array, Date, RegExp, Function等, 統稱為Object型別。   JS變數的

js實現楊輝三角

實現效果:楊輝三角 即: 提示使用者輸入要實現的楊輝三角行數: 請輸入楊輝三角的行數: 8 程式碼實現後的效果如下: 1 1.1 1.2.1 1.3.3.1 1.4.6.4.1 1.5.10.10.5.1 1.6.15.20.15.6.1 1

----如何在js實現公有和私有屬性

私有方法其實和閉包是有關係的,私有方法在其他語言裡面是不被訪問到的,除非有專門的介面,js的區域性作用域裡面的東西在正常情況下也是不能被外部訪問到,但是通過閉包的方式可以訪問到,這樣我們就可以利用這個特性,看例子: var book = (function(){ var page =

js實現button按鈕變灰不可用,可用的方法

按鈕變灰不可用方法:document.getElementById("crop").setAttribute("disabled", true); 按鈕可用方法:document.getElementById("crop").removeAttribute("disabled"); 按