JavaScript變數和作用域的學習筆記,包括變數的含義、作用,機制,以及作用域的機制、JS預解析等 ...
變數
可以理解成一個存放數據的容器,方便多次使用這個值
在命名的時候註意:
1.區分大小寫
2.不用關鍵字和保留字
3.命名有意義(不用拼音和帶數字序號的名稱,可以用下劃線/駝峰來命名,實際開發中遵從統一的命名規則)
數據類型
基本類型
數字、字元串、布爾值、null、undefined
基本類型的值不可修改,類似於化學中的原子(最小單位,不可再分割)
(可能會認為Number類型的值可以修改,但實際上只是用新的數值覆蓋了舊的)
1 var str = "hello world'; 2 var str1 = str.replace('o',''); 3 //str並沒有改變,實際上創建了一個新的字元串並把改變後的字元串的值賦值給它 4 console.log(str); 5 console.log(str1);
基本類型調用方法時,會找到其包裝對象,把屬性和方法借給基本類型,之後包裝對象消失
保存在棧記憶體中,有序排列,大小固定,按照值訪問
值複製時只是把值複製了,複製後修改一個,另一個不變
引用類型
數組、對象
值可以修改,類似於化學中的分子(由多個原子/小分子組成,可以分割)
1 var myhome = { 2 'name':'xh', 3 'age':18, 4 'sex':'male' 5 } 6 myhome.name = 'xm'; 7 delete myhome.sex; 8 //分別輸出xm和undefined 9 console.log(myhome.name); 10 console.log(myhome.sex);
保存在堆記憶體中,大小不固定,依靠棧記憶體中保存的引用類型地址來訪問
複製時為地址引用的複製,複製後修改一個,另一個也變化
如果需要複製值,則需要遍歷對象中每一個元素並複製,實現淺拷貝(只能複製基本類型)
var myhome = { 'name':'xh', 'age':18, 'sex':'male' }; var anotherhome = {}; for(p in myhome){ anotherhome[p] = myhome[p]; } console.log(anotherhome.name); console.log(anotherhome.age); console.log(anotherhome.sex);shallow copy
變數處理
變數相等的比較
1.基本類型和基本類型:直接比較值
2.引用類型和引用類型:指向同一個引用時才相等(如果判斷內容是否相等,需要遍歷其中元素並一一比較)
3.基本類型和引用類型:==比較時,先試圖把引用類型進行轉換(例如數組變成數字),再比較值是否相等,===比較直接返回false
參數傳遞
無論基本類型還是引用類型,傳參時都是傳值(引用類型傳值實際是傳地址,但效果表現為傳值)
類型檢測
1.基本類型:用typeof
2.引用類型:用instanceof(檢測是否為某個引用類型的實例)
變數作用域及生命周期
全局變數:在全局中聲明/沒有用var聲明的變數,一直到所有語句都執行完才被銷毀
局部變數:用var在函數內部聲明的變數,所在的函數執行完就被銷毀
JS中沒有塊級作用域(用{}括起來的範圍)
變數對象
全局變數的對象是window,所有全局裡的變數和函數都可通過window.變數名/函數名訪問到
通過window對象訪問其屬性時,即使該屬性(全局變數中的變數/函數)未定義,也不會報錯,只會返回undefined,而直接訪問該變數/函數時則報錯
作用域鏈
當在某個局部作用域中查找某個對象時,會現在該局部作用域中查找,如果找不到,再向上一層,在上層局部作用域中查找,如此迴圈
因此查找而產生的一條無形的作用域鏈,只能從內到外查找
延長作用域鏈的方法
with會沿著當前局部區域查找對象,找到的話就在當前作用域進行對象值修改,否則就往上查找,找到後會在上一層級中修改變數的值
但不建議使用with語句
JS解析機制
JS先預解析,後逐行解讀代碼
其中函數的參數會被當做該函數的局部變數對待
預解析時,先查找所有var聲明的變數,將其賦值undefined,查找以function開頭的函數,並直接copy內容,之後往函數里走,同樣對函數里var聲明的局部變數賦值undefined,如此迴圈
變數名和函數名衝突時,保留同名的函數
函數名重覆時,保留最後一個同名函數
有些老版本的火狐瀏覽器,無法預解析for、if等語句里定義的函數,因此函數的定義建議放在全局中/函數的內部
垃圾收集
機制
釋放無用的數據,回收記憶體以便後續使用,分為自動收集(JS)和手動收集
原理
找出沒用的數據,打上標記,釋放記憶體,這個過程被垃圾收集器周期性進行
標識無用數據的策略:標記清除、引用計數(不常用,對迴圈引用會產生問題)
記憶體管理(解除引用)
主要是針對全局對象,把其賦值null