JavaScript文法細節——引用與複製
我們都知道,JS中變數的賦值有兩種方式,最近在折騰自己寫的標籤欄外掛程式,碰到了很多平時沒注意的問題。正好,那邊處理清楚了,稍微整理一下關於引用與複製相關知識,可能會不定期增加新碰到的問題,有錯誤希望看到的人指出,避免傳播不正確的知識。 先大致分一下類,參考型別:Object以及其旗下的Array,Date,RegExp,Function;基本封裝類型:Boolean,number,String。 在賦值與傳遞參數的時候,參考型別傳遞的是指標,基本封裝類型是複製新值傳遞。常見的情況我就不囉嗦了,一下主要是一些碰到過的容易理解出錯的情況,以及探究後得出的個人結論。 修改指標變數不一定會影響到引用對象 可能一下不太好理解這個,來點簡單暴力的demo就好說明問題了。 var arr1 = [1, 2, 3], arr2 = arr1; arr2 = [4, 5, 6]; console.log(arr1);console.log(arr2);這個demo比較簡單,結果是:arr1為[1, 2, 3] arr2為[4, 5, 6] 為什麼修改arr2後arr1沒有改變,arr2 = [4, 5, 6]修改的是arr2這個指標變數的指向,並沒有碰到原引用的數組。 下面這種情況則會修改到原對象。 var arr1 = [1, 2, 3], arr2 = arr1; arr2.pop(); console.log(arr1);console.log(arr2);此時的結果為: arr1 arr2都等於[1, 2],arr2.pop()相當於執行[1, 2, 3].pop(),因此arr2引用的原匿名對象被修改了。 因此在操作參考型別的時候,要注意是否修改的是原對象。來一個稍微囉嗦有點的demo: var arr1 = [1, 2, 3], arr2 = arr1; function test (a) { console.log(a); a = [4, 5, 6]; console.log(a);} test(arr2); console.log(arr1);console.log(arr2);上面的輸出結果根據之前的測試應該是 var arr1 = [1, 2, 3], arr2 = arr1; function test (a) { console.log(a); // [1, 2, 3] a = [4, 5, 6]; console.log(a); // [4, 5, 6]} test(arr2); console.log(arr1); // [1, 2, 3]console.log(arr2); // [1, 2 ,3]因為在傳遞arr2給test的時候,相當於執行了a = arr2因此情況跟第一個demo一樣了。同理,將a=[4, 5, 6]改為a.pop(),那麼結果如同第二個demo。 來一個函數自己修改自己的demo: var test = function () { var a = 1; test = function () { var b = 3; }}; test(); console.log(test);此時的test內部為var b = 3;這種方法有個高大上叫法叫惰性載入,具體我就不囉嗦了,可以百度一下或者Google兩下。利用的就是函數本身也是參考型別的特點。 下面的這個demo是參考型別中參考型別: var obj1 = { arr: [1, 2, 3] }, obj2 = obj1; obj2.arr = [4, 5, 6]; console.log(obj1);輸出結果中,obj1被修改了,不難理解執行obj2.arr = [4, 5, 6]時,相當於執行obj1.arr = [4, 5, 6],直接修改了原對象。因此採用簡單的賦值操作得不到一個對象的拷貝。取得拷貝的話可以用for(key in object)的方式遍曆對象進行拷貝。 至於原始類型字串數字之類的基本類型就不多寫了,那些都是複製操作,獲得的是一個新值。