前言
理解js內(nèi)存空間员凝,對于我們理解很多題目大有幫助,特別是一些面試項目奋献。例如下面這個題目:
var a = 20 ;
var b = a ;
b = 30 ;
// 這時a的值是多少?
var m = { a : 10 , b : 20}
var n = m ;
n.a = 15;
// 這時m.a的值是多少
很多朋友搞不清楚健霹。
還有一個this方面的面試題目。大體如下:
var a = 20;
var haoroomsobj = {
a: 10,
c: this.a + 20,
fn: function () {
return this.a;
}
}
console.log(haoroomsobj.c);
console.log(haoroomsobj.fn());
var haoobj=haoroomsobj.fn;
console.log(haoobj())
大家看看上面會輸出什么瓶蚂?下面我就和大家一起來剖析一下這兩個問題糖埋。這兩個問題涉及到js內(nèi)存空間及this關(guān)鍵詞的相關(guān)知識,通過普及這些知識扬跋,來順便解釋一下這兩個題目阶捆。
js內(nèi)存空間
前面我有文章解釋過如何應對js頁面中的[內(nèi)存泄露],但是并沒有解釋js內(nèi)存空間的一些基礎(chǔ)知識钦听。下面我們先來理一下一個概念洒试。
棧與堆
變量對象與基礎(chǔ)數(shù)據(jù)類型(例如:Undefined、Null朴上、Boolean垒棋、Number、String)都放在棧(stack)里
引用數(shù)據(jù)類型痪宰,比如:對象叼架,數(shù)組等一般都放在堆(heap)里
例如如下代碼:
var a1 = 0; // 變量對象
var a2 = 'this is string'; // 變量對象
var a3 = null; // 變量對象
var b = { m: 20 }; // 變量b存在于變量對象中也可以理解為棧,{m: 20} 作為對象存在于堆內(nèi)存中
var c = [1, 2, 3]; // 變量c存在于變量對象中也可以理解為棧衣撬,[1, 2, 3] 作為對象存在于堆內(nèi)存中
基礎(chǔ)數(shù)據(jù)類型也可以理解為棧里的數(shù)據(jù)都是按值訪問乖订,我們可以直接操作保存在變量中的實際的值。但是在堆內(nèi)存中具练,我們不能直接操作對象的堆內(nèi)存空間乍构。在操作堆里的對象時,實際上是在操作對象的引用而不是實際的對象扛点。因此哥遮,引用類型的值都是按引用訪問的。我們可以地把引用理解為保存在變量對象中的一個地址陵究,這個地址是和堆內(nèi)存的值是相關(guān)聯(lián)的眠饮。
那么上面的面試題目我們可以用如下圖來解釋:
因此a還是20
第二個題目:
復制之后是引用的復制。修改了堆里面的對象之后铜邮,n和m對應的是同一個對象仪召,因此輸出m.a會變成15
關(guān)于this
關(guān)于this的解釋,我前面也有過一篇文章松蒜,雖然寫了一點點東西返咱,但是寫的比較淺。下面我就詳細介紹一下this
函數(shù)中的this是難點和重點牍鞠,我今天主要講講函數(shù)中的this
我對函數(shù)調(diào)用總結(jié)了如下三點:
1咖摹、this的指向,是在函數(shù)被調(diào)用的時候確定的
2难述、函數(shù)調(diào)用時萤晴,看其是否被某個對象所擁有,假如被某個對象擁有,那么函數(shù)中的this毅整,指向的是其擁有的對象嫁艇。
例如:
haoroomsobj.fn()
fn()函數(shù)被haoroomsobj所擁有,那么fn里面的this屯断,指向的是haoroomsobj
3、如果函數(shù)獨立調(diào)用,那么該函數(shù)內(nèi)部的this殖演,則指向undefined氧秘。在非嚴格模式中,當this指向undefined時趴久,它會被自動指向全局對象丸相。
例如haoobj() 是獨立調(diào)用,那么haoobj函數(shù)里面的this會指向undefined彼棍,在非嚴格模式下面指向的是全局對象灭忠。
通過上面的三條結(jié)論,我們對于函數(shù)的調(diào)用應該很清楚了座硕,我們再來看下:
haoroomsobj.c
這個不是我們上面所說的函數(shù)情況弛作,因此,還有一個結(jié)論:
當haoroomsobj 在全局聲明時华匾,無論haoroomsobj.c在什么地方調(diào)用映琳,這里的this都指向全局對象,
而當haoroomsobj在函數(shù)環(huán)境中聲明時瘦真,這個this指向undefined刊头,在非嚴格模式下,會自動轉(zhuǎn)向全局對象诸尽。
我們再來看下上面的題目吧:
console.log(haoroomsobj.c);
console.log(haoroomsobj.fn());
var haoobj=haoroomsobj.fn;
console.log(haoobj())
通過上面的結(jié)論原杂,我們可以解釋:
console.log(haoroomsobj.c)
haoroomsob是全局聲明haoroomsobj.c在非嚴格模式下面指向的是window全局對象,因此:
this.a + 20
輸出40
console.log(haoroomsobj.fn());
fn()是haoroomsobj對象下面的函數(shù)您机,這里this指向的是haoroomsobj穿肄,因此輸出的是10
console.log(haoobj())
haoobj()函數(shù)是獨立調(diào)用,指向的是全局际看,因此輸出20
小結(jié)
js內(nèi)存空間咸产,關(guān)鍵理清堆里面的數(shù)據(jù),在操作堆里的對象時仲闽,實際上是在操作對象的引用而不是實際的對象脑溢。
this關(guān)鍵詞要理清函數(shù)調(diào)用,是獨立調(diào)用還是被某個對象所調(diào)用赖欣。獨立調(diào)用在非嚴格模式下面指向的是全局屑彻,被某個對象所調(diào)用,this指向的是某個對象顶吮!