2019-12-16 第三章:函數/小結 + 第四章:變量,作用域與內存問題

7.函數

使用function封裝的語句體。js中的函數可以有返回值也可以沒有返回值。函數或函數的參數都不可以以arguments,eval來命名。

1.理解函數的參數

ECMAScript的參數與其他語言不同,他不在乎參數的類型,也不在乎參數的數量。甚至定義的參數在函數被使用時也不必要被全部傳入。

① js中函數的參數是一個arguments的類數組,可以通過arguments[n]的下標訪問參數值。函數在被調用時,接收到的參數永遠是這個類數組,如果你在函數中定義了兩個參數A與B:

? ? ? ? ? ?arguments[1] = A

? ? ? ? ? ?arguments[2] = B

? ? 其他未被定義的參數值均為undefined,比如arguments[3] = undefined,可以使用arguments.length來確定傳入的非undefined參數的數量。

其中arguments[2] = undefined

② 利用angular這樣的特性,可以寫出針對調用參數個數的偽重載:


如果參數個數為1,執行代碼塊1,否則執行代碼塊2

③ 未定義的參數值為undefined。


2.沒有重載

同樣的函數名被定義兩次,js只會采用后面的那個版本。

重載只能通過上文的方式完成。


8.小結

① js中包括五種基本類型:number,string,boolean,null,undefined。

② 在js中number代表所有數字類型。

③ js中的基本對象類型時object,該類型是js中一切復雜類型的原型。

④ js中的操作符與其他語言基本類似,但要注意一些特殊的,例如boolean操作符返回值的問題(&&和||不一定會返回boolean值)

⑤ js中的函數沒有真正的重載。

⑥ js中函數的參數是一個類數組arguments[],可以通過下標訪問參數內容,使用.length獲取參數個數。




第四章:變量,作用域,內存問題

由于js中的變量不指定類型,因此在變量的生命周期里其可以任意改變其對應的值,類型。這是一個又強大,又容易出現問題的特性。

1.基本類型與引用類型

五種基本值:number,string,null,boolean,undefined為基本類型。基本類型僅代表簡單的數據段。而引用類型值由多個復雜數值組成的對象。

在將值賦給變量時,解釋器會首先區別該變量時哪種類型。引用類型的值是保存在內存中的對象。但是與其他語言不同,js不允許用戶直接訪問內存的地址,換句話說不允許用戶直接操作內存中的對象。因此為了操作對象,js的設計者們發明了引用類型,引用類型指向內存中的對象因此引用類型的值是按引用訪問的。

1.1動態的屬性

定義基本類型和引用類型的步驟是相同的:先聲明(創建變量),再賦值(再為變量賦值)。但是針對引用類型,我們可以為其添加方法與屬性。而基本類型則不可以。

引用類型擁有屬性與方法

1.2復制變量值

從一個變量向另外一個變量復制基本類型與引用類型時是不同的,

有關基本類型的復制:是首先再變量對象上創建一個變量,再將變量的值賦給他。二者操作互相獨立,互不干涉。

基本類型的復制

有關引用類型的復制:首先將儲存在變量對象中的值復制一份放在為新變量分配的空間中,但其實這個值是一個指針,該指針指向儲存在堆中的原變量的對象。復制結束后,實際上兩個變量指向同一個對象。二者行為同步,互相影響。

引用類型的復制


1.3傳遞參數

js中的參數傳遞只有按值傳遞一種。換句話說,把函數外部的值傳入函數中,就如同在做復制的操作,因此也符合上文中復制變量的規則。基本類型就按照基本類型的值復制原則,引用類型就按照引用類型的值復制規則

js中訪問變量有按值訪問與按引用訪問,而傳遞參數只有按值傳遞一種。引用類型在函數中被改變會反應在外部,而基本類型則不會。因為函數內的參數其實是外部參數的復制,值類型互不干涉,引用類型相互影響。

符合變量復制的原則

當然,為了證明js中函數是按值傳遞,還有一種非常經典的證明方法:即傳入引用,但在函數內為引用重新修改指向對象

可以發現外部的引用指向的還是原來的a,而函數內部的a已經指向另外一個對象了

2.執行環境與作用域

執行環境定義了變量或函數有權訪問的其他數據,決定了他們各自的行為。每個執行環境都有一個與之相對應的變量對象(參照前文復制變量的參考圖),環境中所有變量與函數都定義在這里。我們在編碼時一般無法訪問他們,但是解釋器在處理數據時非常依賴他。

全局執行環境在不同的宿主環境下表現也不同。在web環境上通常被認為時window對象,所有全局變量和函數都是作為window的屬性與對象被創建的。環境變量通常在該環境變量中所有的語句都執行完成后被銷毀,而一切在其中定義的變量與函數都隨之銷毀。而全局變量通常只有在程序或網頁被關閉時才被銷毀。

環境區域與變量對象一一對應

每個函數都喲其自己的環境區域,當執行流即將進入一個函數時,首先將該環境區域推進一個環境棧中。在函數執行完成后,將該環境棧彈出,同時將執行流的所有權交還給其上一層的環境區域。循環往復。

環境與環境棧的關系

當代碼在一個環境區域內運行時,會創建變量對象的作用域鏈。其保證了所有對作用域鏈有權訪問的變量與函數有序訪問

作用域鏈的最前端是當前環境區域的變量對象。

? ? 如果當前的環境是函數,則將它的活動對象作為變量對象。活動對象在開始只含有arguments這一個變量。作用域鏈中的下一個變量對象是包含他的環境區域的變量對象。在下一個則是更包含他的全局環境。全局環境的變量對象始終在作用域鏈的末尾。

作用域鏈與變量對象與環境區域的關系

舉個例子來解釋:

函數打印了全局變量的值

再看一個書里的例子:

越在內部可以訪問的變量越多
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容