天天看點

JavaScript—之對象參數的引用傳遞變量函數

1.JavaScript hoisting

>>請看例子,我們拿Chrome的console作為JS的運作環境。

JavaScript—之對象參數的引用傳遞變量函數

上面直接執行console.log(a), 不帶一點懸念地抛出了not defined 錯誤。這是預料之中的。

看下面進化後的代碼:

JavaScript—之對象參數的引用傳遞變量函數

之前變量沒有定義的錯誤沒了,取而代之的是告訴我們a的值是 'undefined'。先不管a的值緣何為 'undefined' 了,至少可以知道現a這個變量是定義了,因為之前報的' a is not defined'的錯誤沒有了。

這正是因為JavaScript 中的一個聲明提前的特性起的作用。

JavaScript—之對象參數的引用傳遞變量函數

第一次對函數foo()的調用同樣報 'not defined' 錯誤。這是合情合理同時是合法的。因為從頭到尾就沒有定義這麼一個叫作foo() 的東西。

之後将函數調用寫在最前面,但函數的定義我們寫在了之後。

>> 再來看上面對a的輸出值為'undefined'的問題。

JavaScript—之對象參數的引用傳遞變量函數

這裡需要深入了解Hoisting這一特性。它的提前隻是将聲明提前,而對變量的指派并沒有跟着提前。這點很關鍵。也就是為什麼我們可以在第一句使用變量a但它的值卻是 'undefined'。 JavaScript裡面聲明了但還未指派的變量其值預設便是 'undefined'。

按照Hoisting來解釋,最終生成的等價代碼其實差不多應該就是這樣的:

JavaScript—之對象參數的引用傳遞變量函數

2.直接對字元串字面量調用其方法

可以直接對字元串字面量調用方法,JS解析器會自動把字元串變量轉為一個字元串類型暫存,然後調用字元串上的方法,完了之後再将暫存的字元串類型銷毀。

是以你會看到下面這種用法。

JavaScript—之對象參數的引用傳遞變量函數

我們可以了解為解析器在背景聲明了一個變量暫存這個字元串然後再調用的length方法。

JavaScript—之對象參數的引用傳遞變量函數

1.匿名函數無法在聲明前調用

正如上面介紹的Hoisting特性,函數可以定義在調用之前也可以定義在調用之後:

JavaScript—之對象參數的引用傳遞變量函數

但僅限于上述這種方式定義的函數。對于匿名函數上述規則不适用。

JavaScript—之對象參數的引用傳遞變量函數

2. 參數變更影響到函數外部

當傳遞給函數的參數是一個數組或對象時,在函數體内對這個傳入的參數的更改會影響到函數體外的原傳入值。

一般說來,對參數的更改不會影響到原來變量的值,更改隻在函數體内起作用:

JavaScript—之對象參數的引用傳遞變量函數

上述代碼中,将name變量指派為'Wayou Liu' 然後傳入change() 函數。在函數體内将傳入的參數值改為'Liu Wayou'。然後再輸出,不出意外地,輸出的是變量原來的值'Wayou Liu'。因為當name傳入change函數後,在函數體内,相當于有一個name的副本,這個副本的值等于name,之後在函數體内對其做的操作是在這個副本上進行的。

但情況有所不同,當傳入的參數是數組、對象時,在函數體内對參數所做的更改會反映到原變量上。

JavaScript—之對象參數的引用傳遞變量函數

可以看出,上面代碼中已經把friut數組的第一個元素更改了。

下面是關于對象的例子:

JavaScript—之對象參數的引用傳遞變量函數

可以很明顯地看到函數體内對參數的改動影響到了原來的變量,這與通常情況下的傳參有質的差別了。需要特别注意。

But,當在函數體内對傳入的數組或對象指派時,這個更改不會反映到函數體外的原變量身上!

請看:

JavaScript—之對象參數的引用傳遞變量函數

按照上面函數内部的更改會反映到原變量的理論,你肯定覺得執行完change()後person變量的name屬性的值已經變成'Tom'了吧。但結果讓人有點難以接受。

原因在于,當在函數體内使用指派操作時,系統就建立了一個變量名為p的變量。這個p是函數内部的變量,對它進行指派當然隻在函數體内起作用,外面的person還是原來的person。

這一步與原來代碼的操作差别僅在于在函數體内是對參數賦新值呢還是對參數的屬性或數組的元素進行更改。

3.使用arguments來接收個數未定的參數

有時候我們寫了個函數但它接收的參數個數不确定,有時候我們在調用一個函數的時候或許也不确定要傳多少個參數。參數需要變成動态的。

這時可以通過函數内arguments來接收傳遞到一個函數的所有參數。

具體說來,就是在函數體内預設有個arguments變量,它儲存了調用這個函數時傳遞來的所有參數,總個數及每個參數的值。它是一個類似于數組的變量,每個參數會成為它的一個元素,可以通過遊标來進行通路。

通過arguments.length可以知道參數個數。

JavaScript—之對象參數的引用傳遞變量函數

繼續閱讀