第四篇 變量曼验、作用域泌射、內(nèi)存

本章我們主要是通過(guò)變量來(lái)使用基礎(chǔ)值和引用值粘姜,理解執(zhí)行上下文(作用域)和理解垃圾回收等

原始值和引用值

js有兩種不同類型的數(shù)據(jù):原始值和引用值。

原始值就是最簡(jiǎn)單的值(undefined熔酷、string孤紧、number、boolean拒秘、Null号显、smybol)
引用值就是由多個(gè)值構(gòu)成的對(duì)象

我認(rèn)為這兩個(gè)值我們最容易弄錯(cuò)的便是他們?cè)趥髦档臅r(shí)候

//基礎(chǔ)值在傳值的時(shí)候是把值賦值給另一個(gè)變量,相當(dāng)于副本
var a = 2;
varb b = a;
//如果把b重新賦值躺酒,a不會(huì)受任何影響押蚤;

//而引用值就不一樣了
var obj1 = new Object();
let obj2 = obj1;
obj2.name="哈哈";
console.log(obj1.name)  //輸入哈哈
//引用值傳值的時(shí)候是把復(fù)制的對(duì)象的指針,相當(dāng)于我復(fù)制了一把我家的門鑰匙阴颖,都還是指向同一個(gè)地址活喊,所以修改一個(gè),另一個(gè)對(duì)象也會(huì)受影響

再提一句:其實(shí)我們只要記住原生值和引用值的特性量愧,不管在傳值還是傳參數(shù)钾菊,一般都不會(huì)弄錯(cuò)

執(zhí)行上下文與作用域

有些東西可能不知道什么是執(zhí)行上下文,其實(shí)我們就可以把他理解為當(dāng)前代碼的運(yùn)行環(huán)境(也就是作用域)在瀏覽器中偎肃,我們所說(shuō)的全局上下文煞烫,就是window對(duì)象。

這里提上一嘴:var定義的全局變量和函數(shù)是window對(duì)象的屬性和方法累颂,但是let和const的頂級(jí)聲明就不會(huì)定義在全局上下文(也就是window對(duì)象)中滞详,但在作用域中解析的效果是一樣的。
函數(shù)參數(shù)是當(dāng)前上下文中的變量紊馏。

為什么要說(shuō)一下這個(gè)呢料饥,是因?yàn)橐屛覀兠靼鬃饔糜虻膯?wèn)題,子作用域可以訪問(wèn)父級(jí)作用域朱监,但父級(jí)作用域不能訪問(wèn)子級(jí)作用域

var a = 1;
function fn(){
  var b = 2;
  console.log(a)岸啡;//輸出1,子級(jí)訪問(wèn)父級(jí)
}
console.log(b)//報(bào)錯(cuò)赫编,因?yàn)楦讣?jí)不能訪問(wèn)子級(jí)作用域

變量聲明

注意:在初始化變量之前一定要先聲明變量巡蘸,不然會(huì)被瀏覽器當(dāng)成全局作用域處理

function fn(){
  age=12;
}
console.log(age) //輸出12

這里在說(shuō)一下var 、let 擂送、const
var聲明會(huì)被拿到函數(shù)或者全局作用域的頂部悦荒,位于作用域所有代碼之前,這個(gè)現(xiàn)象叫做提升嘹吨,提升的好處是在統(tǒng)一作用域下不必考慮變量是否聲明就可以直接使用搬味。但是這種在實(shí)踐中,建議不要使用
let聲明和var聲明相似,let有塊級(jí)作用域身腻,for产还、while匹厘、if等嘀趟,甚至連單獨(dú)的塊({})都是let聲明變量的作用域

for(var i = 0 ; i<10;i++){
}
console.log(i)// 輸出10

for(let i = 0 ; i<10;i++){
}
console.log(i)// 報(bào)錯(cuò)
//這里就可以說(shuō)明var只有函數(shù)作用域,在for這些中愈诚,沒(méi)有作用域她按,使用var聲明的迭代變量會(huì)泄漏到循環(huán)外部

const聲明在使用時(shí)勋桶,必須初始化為某個(gè)值

建議在實(shí)踐中汁尺,如果開發(fā)流程并不會(huì)因此受很大的影響疟呐,就應(yīng)該盡可能的使用const聲明變量豆挽,除非將來(lái)確實(shí)會(huì)修改這個(gè)變量

垃圾回收和性能提升

在js中币他,垃圾回收是計(jì)算機(jī)自己執(zhí)行的挖胃,但在什么時(shí)候執(zhí)行啃洋,這個(gè)不確定碾盐。我們有兩種垃圾回收的方法:標(biāo)記清理引用清理

標(biāo)記清理時(shí)我們最常用的清理方式欢嘿,在運(yùn)行時(shí)衰琐,會(huì)將內(nèi)存中所有的變量進(jìn)行標(biāo)記,然后炼蹦,它會(huì)將所有在本作用域的變量以及被引用的變量的標(biāo)記去掉羡宙,如果在此之后被加上標(biāo)記的變量就會(huì)被清理
引用清理時(shí)將一個(gè)變量賦予一個(gè)引用值,該值為1掐隐,然后這個(gè)值被賦值給另一個(gè)就加一狗热,被覆蓋就減一,如果一個(gè)變量的引用值為0時(shí)虑省,就會(huì)被清理掉(不建議使用)

最佳實(shí)踐:如果一個(gè)數(shù)據(jù)不再有必要匿刮,可以把他設(shè)為null

function fn(name){
  let obj = new Object();
  obj.name=name;
  return obj
}
let myfn = fn("haha"); 
//因?yàn)楹竺娌辉儆斜匾褂眠@個(gè)了  我們就可以把這個(gè)變量設(shè)置為null
//解除myfn對(duì)值的引用
myfn = null
//解除引用的關(guān)鍵是在于確保相關(guān)的值已經(jīng)不再上下文(作用域)里面了

內(nèi)存泄漏的幾種可能

  • 意外聲明全局變量,是最常見的也是最容易修改的內(nèi)存泄漏問(wèn)題
function fn(){
  name="哈哈"
}
  • 定時(shí)器也可能會(huì)導(dǎo)致內(nèi)存泄漏
let name="haha",
setInterval(()=>{
  console.log(name)
},1000)
//只要定時(shí)器一直運(yùn)轉(zhuǎn)探颈,回調(diào)函數(shù)中引用的name就一直占用著內(nèi)存熟丸,垃圾回收程序就不會(huì)清理
  • 使用js閉包很容易在不知不覺間造成內(nèi)存泄漏
let out = function(){
  let name = "haha";
  return function(){
    return name;
};
};
//調(diào)用out()會(huì)導(dǎo)致分配給name的內(nèi)存被泄露,以上代碼創(chuàng)建了一個(gè)閉包膝擂,只要返回的函數(shù)存在就不會(huì)清理name虑啤,因?yàn)殚]包一直在引用它,如果name的內(nèi)容很大,就可能出現(xiàn)問(wèn)題

總結(jié)

js的變量可以保存兩種數(shù)據(jù)類型的值:基礎(chǔ)值引用值,基礎(chǔ)值包含Boolean,undefined架馋、null狞山、number、String叉寂、Symbol萍启。下面我們所說(shuō)這兩種值的特點(diǎn):

  • 原始值大小固定,因此保存在棧內(nèi)存中;而引用值是對(duì)象勘纯,保存在堆內(nèi)存中
  • 從一個(gè)變量到另一個(gè)變量復(fù)制原始值相當(dāng)于是創(chuàng)建了這個(gè)值的副本
  • 從一個(gè)變量到另一個(gè)變量復(fù)制引用值實(shí)際上只會(huì)復(fù)制指針局服,因此結(jié)果是兩個(gè)變量都指向同一個(gè)對(duì)象
  • 包含引用值的變量,實(shí)際上是包含的這個(gè)對(duì)象的指針而不是對(duì)象本身
  • typeof操作符可以確定值的原始類型驳遵,引用類型都返回object淫奔;而instanceof操作符用于確保值的引用類型

任何變量都存在于某個(gè)執(zhí)行上下文中(也就是作用域),這個(gè)上下文決定了變量的生命周期堤结,以及他們可以訪問(wèn)的內(nèi)容有哪些

  • 執(zhí)行上下文分全局上下文唆迁、塊級(jí)上下文、函數(shù)上下文(局部作用域包括塊級(jí)和函數(shù)作用域)
  • 代碼執(zhí)行每一個(gè)上下文時(shí)竞穷,都會(huì)創(chuàng)建一個(gè)作用域鏈唐责,用于搜索變量和函數(shù)
  • 局部作用域不僅可以訪問(wèn)自己作用域內(nèi)的變量,還可以訪問(wèn)上層作用域乃至全局作用域的內(nèi)容
  • 全局作用域只能訪問(wèn)全局作用域的變量和函數(shù)瘾带,不能訪問(wèn)局部上下文中的任何數(shù)據(jù)
  • 變量的執(zhí)行上下文用于確定什么時(shí)候釋放內(nèi)存

js是使用垃圾回收的編程語(yǔ)言鼠哥,我們不需要擔(dān)心內(nèi)存分配和回收。

  • 離開當(dāng)前我們?cè)L問(wèn)作用域的值看政,會(huì)被標(biāo)記為可回收朴恳,然后在垃圾回收期間被刪除
  • 主流的垃圾回收算法是標(biāo)記清理,即先給當(dāng)前不使用的值加上標(biāo)簽帽衙,再回來(lái)回收他的內(nèi)存
  • 引用計(jì)數(shù)是另一種垃圾回收策略菜皂,需要記錄值被引用了多少次。js引擎已經(jīng)不再使用這種算法了厉萝,但在一些舊版本的IE仍然會(huì)受這種算法的影響恍飘,原因是js會(huì)訪問(wèn)非原生js對(duì)象(如DOM元素)
  • 解除變量的引用不僅僅可以消除循環(huán)引用而且對(duì)垃圾回收也有幫助。為促進(jìn)內(nèi)存回收谴垫,全局對(duì)象章母、全局對(duì)象的屬性和循環(huán)引用都應(yīng)該在不需要時(shí)解除引用。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末翩剪,一起剝皮案震驚了整個(gè)濱河市乳怎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌前弯,老刑警劉巖蚪缀,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異恕出,居然都是意外死亡询枚,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門浙巫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)金蜀,“玉大人刷后,你說(shuō)我怎么就攤上這事≡ǔ” “怎么了尝胆?”我有些...
    開封第一講書人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)护桦。 經(jīng)常有香客問(wèn)我含衔,道長(zhǎng),這世上最難降的妖魔是什么嘶炭? 我笑而不...
    開封第一講書人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任抱慌,我火速辦了婚禮,結(jié)果婚禮上眨猎,老公的妹妹穿的比我還像新娘。我一直安慰自己强经,他們只是感情好睡陪,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著匿情,像睡著了一般兰迫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上炬称,一...
    開封第一講書人閱讀 49,950評(píng)論 1 291
  • 那天汁果,我揣著相機(jī)與錄音,去河邊找鬼玲躯。 笑死据德,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的跷车。 我是一名探鬼主播棘利,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼朽缴!你這毒婦竟也來(lái)了善玫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤密强,失蹤者是張志新(化名)和其女友劉穎茅郎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體或渤,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡系冗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了劳坑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毕谴。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出涝开,到底是詐尸還是另有隱情循帐,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布舀武,位于F島的核電站拄养,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏银舱。R本人自食惡果不足惜瘪匿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望寻馏。 院中可真熱鬧棋弥,春花似錦、人聲如沸诚欠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)轰绵。三九已至粉寞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間左腔,已是汗流浹背唧垦。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留液样,地道東北人振亮。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蓄愁,于是被迫代替她去往敵國(guó)和親双炕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容