寫冒泡排序時,遇到一個問題:數組
function bubbleSort(arr){ var temp = 0; console.log("傳入的數組:"); console.log(arr); for(var i = 0;i<arr.length;i++){ //循環arr.length-1次 console.log("外層第"+i+"次循環===============start"); for(var j = 0;j<arr.length-1;j++){ //循環arr.length-1-1次 if(arr[j]<arr[j+1]){ //倒敘排列數組:若是相鄰的兩個,前面那個比後面那個小,就互換 temp = arr[j]; // —┐ arr[j] = arr[j+1]; // —├—藉助中間變量將數組中的兩個值進行互換 arr[j+1] = temp; // —┘ } console.log("內層"+j+"次循環"); console.log(arr); } console.log("外層第"+i+"次循環===============end"); } return arr; }
var array = [2,3,9,5,7,1,8]; var sortArray = bubbleSort(array); console.log("array "+array);//array 9,8,7,5,3,2,1 console.log("sortArray "+sortArray);//sortArray 9,8,7,5,3,2,1 //好奇爲何array也被排序了嗎?
看下面的研究:函數
我首先想到的是,是否是return的問題。難道我腦子裏少記了一個return的不知道的關鍵做用?性能
先測試一下:測試
function foo(bar){ bar = 1; return bar; //return 3; } var a = 0; var b = foo(a); console.log(a) //0 console.log(b) //1 //若是return 3 就獲得3 //不加return, function foo2(bar2){ bar2 = 1; } var a2 = 0; var b2 = foo2(a2); console.log(a2) //0 console.log(b2) //undefined
return就是用來返回函數值的,它真的沒什麼特殊的神奇的功效。
其實就是直接刪掉return,試一下就知道是否是了,我怎麼會懷疑這個。
等等,爲何上面的a不會被修改掉啊,難道跟a是數字有關?
那這裏的問題應該就出在數組上。spa
數組怎麼了?關於JavaScript的數據類型和賦值原理的這一塊知識,個人腦子裏模糊了。3d
先來段代碼試試:指針
function foo(bar){ bar = [1,2,3,4]; return bar; } var a = [1,2,3]; var b = foo(a); console.log(a) //[1,2,3] console.log(b) //[1,2,3,4] function foo2(bar2){ bar2[0] = 0; return bar2; } var a2 = [1,2,3]; var b2 = foo(a2); console.log(a2) //[0,2,3] console.log(b2) //[0,2,3]
兩個函數一樣是數組,爲何結果不同?code
上面緣由在於數組是引用數據類型對象
關於js數據類型的研究
js中數據類型分爲:
string,number,boolean,[],{},null,undefined
字符串,數字,布爾,數組,對象,null,undefinedblog
null和undefined區別????-------------------------------------undefined:聲明變量但未初始化,null,找不到該對象
null==undefined//true
null===undefined//false
上面的數據類型能夠分類
原始類型和引用類型
原始類型:undefined,null,boolean,number,string
引用類型:[],{}
在許多語言中,字符串string都被看做引用類型,而非原始類型,由於字符串的長度是可變的,可是js打破了這一傳統。
可是,JavaScript擁有動態類型的,也就是說,一個變量能夠被賦值成不一樣的類型。
那麼咱們接下來就不考慮糾結變量是哪一種數據類型了,每一個數據類型有怎樣怎樣了了,咱們直接從 變量的值 的角度 來繼續思考
在js中,一個變量能夠擁有兩種類型的值(參考上面數據類型)
原始值和引用值
原始值:存儲在棧(stack)中的簡單數據段,也就是說,他們的值直接存儲在變量訪問的位置
引用值:存儲在堆(heap)中的對象,也就是說,存儲在變量處的值是一個指針(point),指向存儲對象的內存處。
因此,在爲變量賦值時,JavaScript的解釋程序必須先判斷該值是原始類型仍是引用類型。
要實現這一點,JavaScript解釋程序則需嘗試判斷該值是不是JavaScript的原始類型之一。原始類型有哪些上面已經說過了。
若是是原始類型,因爲原始類型佔據的空間是固定的,因此在內存中,他們被存儲在棧中,這樣子便於快速查詢變量的值。(關於string長度可變看上面)
若是是引用類型,那麼它的存儲空間將從堆中分配。緣由是由於,引用值的大小會改變,因此不能把他們放在棧中,不然會下降變量查詢的速度。所以咱們就把該對象在堆中的地址放在棧中。地址的大小是固定的,因此對變量性能無任何負面影響。
如圖所示:
------------------------------------------------這上面相關知識來源:http://www.w3school.com.cn/js/pro_js_value.asp
------------------------------------------------這下面相關知識來源:https://www.zhihu.com/question/26042362/answer/31903017
因此上面的出現的問題也就好解釋了。
能夠簡化成這樣:
var a = [1,2,3]; var b = a; a = [4,5,6]; alert(b); //[1,2,3] var a = [1,2,3]; var b = a; a.pop();//內置函數,刪掉數組最後一個 alert(b); //[1,2]
圖解就是這樣:
就算是調用函數
var b = foo(a)
只要這個函數裏面的操做直接操做傳入的數組對象自己,那麼就是在操做堆中的對象。
就會修改到自身。
只要是沒有操做它自己,而是在堆裏建立了一個新的對象,而後從新將棧中b的引用地址修改過去。
就不會修改自身。
拓展閱讀;https://zhuanlan.zhihu.com/p/24080761