1. 程式人生 > >javascript關於物件深拷貝和陣列去重的問題...

javascript關於物件深拷貝和陣列去重的問題...

中秋最後一天假期,還是憋屈在家裡,沒事可做,發發關於兩個看似很基礎卻又很有意義的兩個問題的一點感想,如題...

一.物件深拷貝:

對應的淺拷貝,物件是通過地址指向來獲得引用的,所以單純的用一個新物件指向源物件就是淺拷貝,對新物件的操作同樣會影響的源物件。好比小明有個U盤,裡面裝有一些資料,一天,小紅也需要這個U盤裡的資料,於是拿過來改了裡面的資料,結果小明再用時,裡面資料就變了,因為兩個人用的其實是同一個u盤嘛... 如下:

1 2 3 4 5 varobj = {a:'a'}; varobj1 = obj; obj.a = 'a1'; alert(obj.a); alert(obj1.a);

執行

那麼怎麼樣才能資料各自私有而不影響對方呢,顯而易見嘛,讓小紅也去買個u盤,並把資料也拷一份到她的u盤裡,各用個的就行了。於是:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 functionclone(myObj) { if(typeof(myObj) !='object' || myObj == null)return myObj; varmyNewObj = newObject(); for(vari inmyObj) myNewObj[i] = clone(myObj[i]);//遞迴呼叫,當物件中又有物件時 returnmyNewObj; } var
obj = {a:'a'}; varobj1 = obj; varobj2 = clone(obj); obj.a = 'a1'; alert(obj.a); alert(obj1.a); alert(obj2.a);

執行

至此,區別也很明顯了,obj1淺拷貝由於是訪的同一個物件,故改變源物件obj,新物件obj1也隨之改變。而深拷貝obj2是新建了一個物件例項,與源物件obj互不干擾。

二.關於陣列去重

網上很流行一種解法,如下:

1 2 3 4 5 6 7 8 9 10 Array.prototype.filter =function(){ for(vari=0,temp={},result=[],ci;ci=
this[i++];){ if(temp[ci])continue; temp[ci]=1; result.push(ci); } returnresult; } varaa=['1','2','3','1','2']; alert(aa.filter());

執行

它其實是用了物件的特性,把每個陣列元素當做一個物件的屬性來判斷是否存在,這樣做有個好處是不用二次遍歷陣列。然而,乍一看結果沒問題,可是一旦數組裡有了number,布林值,物件等作為元素的時候,就會發現問題了。
原因在於:物件則要求其屬性值必須為字串,如果提供給物件的屬性不是字串,那麼則會自動呼叫 toString 方法轉化為字串形式,於是,嚴格來講,這種方法只能在陣列元素全為字串時才成立

我們再看看jquery的原始碼是怎麼實現陣列去重的方法的:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 unique: function( array ) {  varret = [], done = {};  try for( vari = 0, length = array.length; i < length; i++ ) {  varid = jQuery.data( array[ i ] );  if( !done[ id ] ) {  done[ id ] =true ret.push( array[ i ] );  }catch( e ) {  ret = array;  }   returnret;  }, 

乍一看,其實思路跟我上面說的方法是一樣的,可是別忘了很重要的一點,var id = jQuery.data( array[ i ] );這一句,其實是把每個陣列元素都轉換成了節點陣列再做的判斷。

所以,如果把安全性放在首位,效率次之的話,陣列去重還是應該老老實實二次遍歷陣列,如下:

1 2 3 4 5 6 7 8 9 10 11 12 functionundulpicate(array){  for(vari=0;i<array.length;i++) {  for(varj=i+1;j<array.length;j++) {  //注意 ===  if(array[i]===array[j]) {  array.splice(j,1);  j--;  returnarray;  }

當然,如果能確定陣列元素型別,大可不必這樣做,畢竟二次遍歷在資料量大的時候是個不小的消耗。。
此外,貌似hash查詢可以減少一次遍歷...具體還沒想過...唉,今天就到此位置吧

相關推薦

javascript關於物件拷貝陣列的問題...

中秋最後一天假期,還是憋屈在家裡,沒事可做,發發關於兩個看似很基礎卻又很有意義的兩個問題的一點感想,如題... 一.物件深拷貝: 對應的淺拷貝,物件是通過地址指向來獲得引用的,所以單純的用一個新物件指向源物件就是淺拷貝,對新物件的操作同樣會影響的源物件。好比小明有個U盤,裡面裝有一些資料,一天,小紅也需要這

JavaScript拷貝拷貝

復制 nsh book 並不會 turn 字符串 重要 jce 兩種 原文   簡書原文:https://www.jianshu.com/p/3d930756dd8f 大綱   前言  1、對深拷貝和淺拷貝的初步認識  2、深拷貝和淺拷貝的區別  3、淺拷貝存在的缺陷  4

JavaScript拷貝拷貝

前言 工作中會經常遇到運算元組、物件的情況,你肯定會將原陣列、物件進行‘備份’當真正對其操作時發現備份的也發生改變,此時你一臉懵逼,到時是為啥,不是已經備份了麼,怎麼備份的陣列、物件也會發生變化。如果你對拷貝原理理解的不透徹,此文或許能提供一點幫助。 javascript資料型別 基本資料型別 string、

物件拷貝拷貝

寫在前面 各類技術論壇關於深拷貝的部落格有很多,有些寫的也比我好,那為什麼我還要堅持寫這篇部落格呢,之前看到的一篇部落格中有句話寫的非常好 學習就好比是座大山,人們沿著不同的路登山,分享著自己看到的風景。你不一定能看到別人看到的風景,體會到別人的心情。只有自己去登山,才能看到不一樣的風景,體會才更加

es6中Array.from()陣列

Array.from() 1.複製陣列,如果傳的是陣列,將把陣列複製一份傳給新陣列。 let arr = [1,2,3,4,5]; let arr2 = Array.from(arr); console.log(arr) // [1,2,3,4,5] con

陣列迴圈遍歷優化陣列演算法

陣列去重演算法: array.sort(function(a,b){    return a<b ? 1:(a > b ? -1 :0); });  newArray=[array[0]]; for(var i=0,len =array.length;i<

20180426-vue反選案例陣列

let flag = true;                                 //定義flag為全選 for(var i = 0; i < List.length; i++){ //遍歷陣列 if(!List[

JavaScript的函式(定義與解析、匿名函式、函式傳參、return關鍵字)陣列(操作資料的方法、多維陣列陣列

函式 函式就是重複執行的程式碼片。 1、函式定義與執行 <script type="text/javascript"> // 函式定義 function aa(){ alert('hello!'); } // 函式執行

拷貝陣列物件

function deepClone(obj){ let objClone = Array.isArray(obj)?[]:{}; if(obj && typeof obj==="object"){ for(var key in

拷貝拷貝陣列物件的深淺拷貝

 淺拷貝 只是拷貝了基本型別的資料,而引用型別資料,複製後也是會發生引用,我們把這種拷貝叫做淺拷貝(淺複製) 物件淺拷貝: var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = obj1; obj2.b = 100; consol

JAVA陣列JavaScript陣列比較

JS的直覺方案: 對於陣列去重,只要寫過程式的,立刻就能得到第一個解法: function unique(arr) { var ret = [] for (var i = 0; i < arr.length; i++) {

陣列 簡單的(利用物件typeof的封裝

利用物件的屬性不會重複的原理進行去重  把數組裡的每一位放在物件裡面,當做它的屬性名,挨個訪問這物件的屬性名看有沒有這個屬性值 <script> var arr =[1,1,1,2,2,2,2,2,3,3,5,6,7]; Array

javascript學習總結之物件拷貝拷貝

前言 最近在寫ES6的文章的時候發現重複遇到關於javascript深拷貝和淺拷貝的問題,然後查找了一些資料,根據資料和自己的理解做了以下筆記,畢竟javascript關於深拷貝和淺拷貝的問題在一些面試的時候有些面試官可能會進行提問,一起來看看吧! 資料型別 在瞭解淺拷貝和深拷貝之前,我們先回顧一下ja

C++本質:類的賦值運算符=的載,以及拷貝拷貝

fin 過程 種類 解決 對象的引用 執行 面向 鏈式 alt 關鍵詞:構造函數,淺拷貝,深拷貝,堆棧(stack),堆heap,賦值運算符摘要: 在面向對象程序設計中,對象間的相互拷貝和賦值是經常進行的操作。 如果對象在申明的同時馬上進行的初始化操作,則

JavaScript 一維陣列、二維陣列方法

1.使用ES6語法 set方法陣列去重:: a=[1,2,3,4,1,2,3,4]; [...new Set(a)]; //[1, 2, 3, 4] 2.一維陣列去重方法 function unique1(array){ var n = []; //一個新的臨時陣列

JavaScript中的拷貝拷貝方法總結

在日常的程式碼書寫中常常會遇到拷貝問題,今天我們就來總結一下常用的淺拷貝和深拷貝都有哪些實現方法。 淺拷貝常用方法: slice var arr1=[1,2],arr2=arr1.slice(); console.log(arr1);//[1,2] console.log(a

vue根據陣列物件總某個唯一標識

由於在vue中,會自動在陣列和物件中加入_obser__觀察者模式的一些屬性,所以直接用陣列的filter去重(下面這種),indexOf不能準確識別 var arr = [1, 2, 2, 3, 4, 5, 5, 6, 7, 7]; var arr2 = arr.filter(function(x

JavaScript 實現陣列

JavaScript 實現陣列去重 演示Demo 陣列去重 // 方法一 function unique1(a) { var res = []; for (var i = 0, len = a.length; i < len; i++) { for (var j =

深入剖析javaScript中的拷貝拷貝

在面試時經常會碰到面試官問:什麼是深拷貝和淺拷貝,請舉例說明?如何區分深拷貝與淺拷貝,簡單來說,假設B複製了A,當修改A時,看B是否會發生變化,如果B也跟著變了,說明這是淺拷貝,如果B沒變,那就是深拷貝;我們先看兩個簡單的案例: //案例1(深拷貝) var a1 = 1, a2= a1; conso

陣列物件根據物件中指定的屬性?你知道多少

有一天有一個朋友給我發來訊息 “陣列物件根據物件中指定的屬性去重?讓我寫寫看”,看到這個的時候我有點懵逼,好像不太會。 我只能咬著牙硬著頭皮死磕,差點從入門到放棄,在朋友一步一步指導下面終於寫好了,朋友總結好了發了我一份,本著自願共享的精神。過來兩天我就把這個給忘了 在專案中剛好遇到這個東西,那時候腦子僅