【JS學習筆記】第四章變量、作用域和內存問題

JS 變量松散類型的本質,決定了變量只是在特定時間保存特定值的一個名字而已,而不存在定義某個變量的數據類型的規則,因此變量的值及其數據類型可以在腳本的生命周期內發生改變。

  • 基本類型的值是指簡單的數據段,引用類型的值指由可能有多個值構成的對象。

  • 基本數據類型有5種:string, number,boolean,null,undefined. 它們按值訪問,因此可以操作保存在變量中實際的值。

  • 在賦值給變量時,解析器必須確定這個值是基本類型的值還是引用類型的值。

  • 引用類型的值是保存在內存中的對象。js 不允許直接訪問內存中的位置,也就是不能直接操作對象的內存空間。因此,在操作對象時,是在操作對象的引用,而不是實際的對象。

動態屬性

對基本類型和引用類型的變量值進行操作的方法不同。
對于引用類型的值,可以為其添加、刪除、更改屬性和方法:

var person = new Object();
person.name = "Nicholas";
alert(person.name); //"Nicholas"

alert ()是一個函數。通過函數訪問屬性
如果對象不被銷毀或者這個屬性不被刪除,則這個屬性將一直存在。

基本類型的值卻不能添加屬性。

復制變量值

從一個變量向另一個變量復制基本類型值和引用類型值時,也存在不同。

復制基本類型的值時,會在變量對象上創建一個新值然后把該值復制到為新變量分配的位置上

var num1 =5;
var num2 = num1;
IMG_8065.JPG

復制引用類型的值時,也會將存儲在變量對象中的值復制一份放到為新變量分配的空間中。不同在于,這個值的副本是一個指針,這個指針指向存儲在堆中的一個對象。復制操作結束后,兩個變量引用同一個對象。改變其中一個變量,會影響另一個。

IMG_8066.JPG

傳遞參數

ECMAScript 中所有函數的參數都是按值傳遞的。
在向參數傳遞基本類型的值時,被傳遞的值會被復制給一個局部變量(即命名參數,arguments對象中的一個元素)。
在向參數傳遞引用類型的值時,會把值在內存中的地址復制給一個局部變量,因此這個局部變量的變化會反映在函數的外部。

https://www.zhihu.com/question/27114726

檢測類型

檢測基本數據類型用 typeof s
如果變量的值是一個對象或null,則會返回object

檢測引用類型的值,則用instanceof constructor
示例: alert(person instanceof Object/Array/RegExp) //true or false
所有引用類型的值都是Obeject的實例。因此在檢測一個引用類型的值和Object構造函數時,instanceof 操作符始終返回true。如果使用instanceof 操作符檢測基本類型的值,則返回false,因為基本類型不是對象。

執行環境及作用域

執行環境,execution context,簡稱環境,定義了變量或函數有權訪問的其他數據,決定了各自的行為。每個執行環境都有一個與之關聯的變量對象(variable object),環境中定義的所有變量和函數都保存在這個對象中。編寫代碼無法訪問這個對象,但解析器在處理數據時會在后臺使用它。

全局執行環境是最外圍的一個執行環境。在web瀏覽器中,全局執行環境是Window對象,所有全局變量和函數都是作為 Window的屬性和方法創建的。某個執行環境中所有代碼執行完畢后,該執行環境被銷毀,保存在其中的所有變量和函數定義也隨之銷毀。

每個函數都有自己的執行環境。當執行流進入一個函數時,函數的環境就會被推入到一個環境棧中,函數執行之后,棧將其環境彈出,把控制權返回給之前的執行環境。ECMAScript程序中的執行流正是由這個方便的機制控制著。

當代碼在一個環境中執行時,會創建變量對象的一個作用域鏈(scope chain)。用途是保證對執行環境有權訪問的所有變量和函數的有序訪問。作用域鏈前端,是當前執行代碼所在環境的變量對象。如果這個環境是函數,則將其活動對象(activation object)作為變量對象。活動對象最開始只包含一個變量,即arguments對象。作用域鏈中下一個變量對象來自包含(外部)環境,再下一個變量對象在來自下一個包含環境,最后是全局執行環境。

標識符解析是沿著作用域鏈一級一級地搜索標識符的過程。

延長作用域鏈

可以在作用域鏈的前端臨時增加一個變量對象,該變量對象會在代碼執行后被移除。

function buildUrl(){
     var qs = "?debug=true";
     with (location){
              var url=href +qs;
      }
      return url;
  }

with 語句接收的是location對象,因此其變量對象中就包含了 location對象的所有屬性和方法,
href實際上是location.href

沒有塊級作用域

在其中c語言中,由花括號封閉的代碼都有自己的作用域,因而支持根據條件來定義變量。比如以下例子中,color會在if語句執行完畢后被銷毀

if(true) {
   var color = "blue";
  }
  alert(color); //"blue"

但在js中,if語句中的變量聲明會將變量添加到當前的執行環境,這里是全局環境。

for (var i=0;i<10;i++){
      doSomething(i);
}

alert(i);//10

對于塊級作用域的語言來說,for語句初始化變量的表達式所定義的變量,只會存在于循環的局部環境。而對于JS來說,變量i即使在for循環結束后,也依舊會存在于循環外部的執行環境中。

  1. 變量聲明
    使用var聲明的變量會自動被添加到被接近的環境中,在函數內部,最接近的環境就是函數的局部環境。下面例子中,sum被var聲明,添加到add()函數的局部環境中,因此在全局環境中訪問時,是導致錯誤。這里如果省略var,則sum會被添加到全局環境中。
function add(num1,num2) {
    var sum =num1 + num2 ;
    return sum;
}
var result = add(10,20);//30
alert(sum); //導致錯誤

訪問局部變量要比訪問全局變量更快,因為不用向上搜索作用域鏈。

垃圾收集

js具有自動垃圾收集機制,不用手動跟蹤內存的使用情況。

函數中的局部變量只在函數執行的過程中存在,因此在函數執行完畢后,對其打上標記,將來回收其內存。

標記清除

mark-and-sweep
當變量進入環境時(例如在函數中聲明一個變量),將這個變量標記為進入環境,而當變量離開環境時,則將其標記為離開環境。

垃圾收集器在允許的時候回給存儲在內存中的所有變量都加上標記,然后去掉環境中的變量以及被環境中變量引用的變量的標記,在此之后,再被加上標記的變量將被視為準備刪除的變量。最后,垃圾收集器完成內存清楚工作,銷毀那些帶標記的值回收其占用的內存空間。

另一種是引用計數

性能問題

當環境中存在256個變量,4096個對象,64K的字符串,任意一種都會觸發垃圾回收機制,但如果環境中一直都有這么多變量存在,那么垃圾回收器會一直工作。

因此,如果垃圾回收器回收的內存分配量低于程序占用內存的15%,說明大部分內存不可被回收,那么把臨界條件翻倍,如果回收的內存高于85%,說明大部分內存該清理了,把臨界值重置為默認值。

管理內存

JS中,分配給web瀏覽器的可用內存數量通常比分配給桌面應用程序的少,處于安全考慮。內存限制問題不僅會影響給變量分配內存問題,還會影響調用棧以及在一個線程中能夠同時執行的語句數量。

因此,為了讓頁面獲得更好的性能,我們需要占用最少的內存,優化內存占用,只為執行中的代碼保存必要的數據。一旦數據不再有用,可將其值設置為null釋放其引用,這個做法叫做解除引用(dereferencing)。一般用于釋放全局變量的內存,因為局部變量在離開執行環境時自動被解決引用。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,247評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,520評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,362評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,805評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,541評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,896評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,887評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,062評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,608評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,356評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,555評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,077評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,769評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,175評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,489評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,289評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,516評論 2 379

推薦閱讀更多精彩內容