原始值和引用值
除了object外的變量都是原始值牺弹,引用值就是對(duì)象浦马,對(duì)象實(shí)際上保存在內(nèi)存空間时呀,而js不允許訪(fǎng)問(wèn)內(nèi)存空間,因此在對(duì)對(duì)象進(jìn)行任何操作時(shí)捐韩,操作的就是這個(gè)引用(reference)
- 用new時(shí)有區(qū)別
let name1 = "lpj";
let name2 = new String("lpj")'
name1.age = 19;
name2.age = 19;
console.log(name1.age);//undefined name1類(lèi)型為string
console.log(name2.age);//19 name2類(lèi)型為object
對(duì)象的“復(fù)制”
把引用值從一個(gè)變量賦給另一個(gè)變量時(shí)退唠,其儲(chǔ)存的值也會(huì)復(fù)制,區(qū)別在于荤胁,這個(gè)值是指向這個(gè)對(duì)象的指針傳參只傳值不傳引用
function setName(obj){
obj.name = "lpj"
obj = new Object({
name:"hjy"
})
}
let person = Object()
setName(person)
console.log(person.name)//lpj而非hjy
在函數(shù)內(nèi)部 obj和person都指向同一個(gè)對(duì)象瞧预,obj.name = "lpj"
可以成功對(duì)這個(gè)對(duì)象進(jìn)行操作,但是obj = new Object
后仅政,obj會(huì)被設(shè)置為一個(gè)新的引用值(新指針值)垢油,而非把這個(gè)引用指向一個(gè)新對(duì)象,這說(shuō)明了傳參時(shí)不會(huì)傳引用圆丹,而只是傳了個(gè)指針值滩愁。換句話(huà)說(shuō),跟c++不同辫封,c++傳一個(gè)數(shù)組變量進(jìn)來(lái)硝枉,然后清空,那就是直接清空了倦微。
上下文和作用域鏈 P89
變量或函數(shù)的上下文(即作用域)決定了他們能訪(fǎng)問(wèn)哪些數(shù)據(jù)以及他們的行為
每個(gè)上下文都有一個(gè)關(guān)聯(lián)的變量對(duì)象
妻味,這個(gè)上下文中的所有變量和函數(shù)都存在這個(gè)對(duì)象上,這個(gè)以一定順序排列鏈接變量對(duì)象
的集合就稱(chēng)為作用域鏈欣福,當(dāng)前作用域的變量對(duì)象始終在鏈的最前
這樣就可以按順序去進(jìn)入各個(gè)作用域的變量對(duì)象责球,從而訪(fǎng)問(wèn)數(shù)據(jù)。
舉個(gè)例子說(shuō)明作用域鏈規(guī)則
簡(jiǎn)單來(lái)說(shuō):變量對(duì)象就像一個(gè)個(gè)車(chē)間拓劝,里面按順序裝著不同機(jī)器和原料
(如果是全局變量對(duì)象Windows的話(huà)雏逾,那就是總工廠(chǎng),各種車(chē)間(函數(shù)郑临、對(duì)象)和各種總工廠(chǎng)原料(全局變量)都算是這個(gè)工廠(chǎng)的機(jī)器/原料(屬性))
作用域鏈就像一條單向傳送帶連接不同車(chē)間栖博,從小車(chē)間連向大車(chē)間最終連向總工廠(chǎng)
函數(shù)在創(chuàng)建和執(zhí)行時(shí)發(fā)生了什么?待辦什么是context厢洞,https://blog.csdn.net/konglingyuan/article/details/51441829
- 創(chuàng)建時(shí):創(chuàng)建Function對(duì)象的內(nèi)部屬性[[scope]]仇让,包含了一個(gè)函數(shù)當(dāng)前作用域中對(duì)象的集合,即當(dāng)前作用域的變量對(duì)象(是嗎)犀变,這個(gè)集合就是
函數(shù)的
作用域鏈
它決定哪些數(shù)據(jù)可以被函數(shù)所訪(fǎng)問(wèn)妹孙,它將把自己完全復(fù)制到執(zhí)行環(huán)境的作用域鏈中
- 執(zhí)行時(shí):為函數(shù)創(chuàng)建一個(gè)執(zhí)行環(huán)境(execution context)內(nèi)部對(duì)象
該對(duì)象與函數(shù)一一對(duì)應(yīng)秋柄,會(huì)重復(fù)創(chuàng)建获枝,執(zhí)行完畢即銷(xiāo)毀 - 為執(zhí)行環(huán)境初始化作用域鏈,初始化為當(dāng)前函數(shù)的[scope]](即
函數(shù)的
作用域鏈)的對(duì)象
注意 這里的作用域鏈不是上面的
函數(shù)的
作用域鏈骇笔,而是屬于環(huán)境的省店,用于解析標(biāo)識(shí)符
至此嚣崭,活動(dòng)對(duì)象創(chuàng)建完畢,成為函數(shù)運(yùn)行時(shí)的一個(gè)變量對(duì)象
作用域鏈增強(qiáng)
指原本作用鏈前端對(duì)應(yīng)的變量對(duì)象被換成了別的變量對(duì)象
try/catch的catch(創(chuàng)建新的變量對(duì)象)以及with語(yǔ)句(挪動(dòng)變量對(duì)象到最前端)-
變量的作用域聲明
- var
在函數(shù)里var name懦傍,外面訪(fǎng)問(wèn)不到雹舀,因?yàn)檫@個(gè)變量被添加到這個(gè)函數(shù)上下文的變量對(duì)象當(dāng)中了但是如果不var,直接寫(xiě)name粗俱,會(huì)自動(dòng)添加為全局變量说榆,放在全局變量對(duì)象當(dāng)中- 提升(有點(diǎn)抽象)
var name = "lpj"
等價(jià)于name = "lpj"; var name
也就是說(shuō) var在執(zhí)行的時(shí)候,這個(gè)聲明會(huì)被提升到頂端(函數(shù)頂端或全局頂端)寸认,但是這個(gè)賦值卻不會(huì) 舉例:
- 提升(有點(diǎn)抽象)
- var
console.log(name)//undefined
var name = 'lpj'//聲明被提升 但是賦值沒(méi)被提升
let
塊作用域:指最近的一堆{}就是一個(gè)塊签财,這解釋了為什么使用let可以防止for語(yǔ)句的i泄露出去標(biāo)識(shí)符查找 P93
就是指沿著作用域鏈搜索這個(gè)變量的過(guò)程,如果在當(dāng)前作用域找到了color = ''blue''
查找即停止偏塞,在父級(jí)的color = "green"
就不會(huì)生效
內(nèi)存與性能P95
- 垃圾回收
每隔一段時(shí)間判定哪個(gè)變量不會(huì)再使用了唱蒸,就釋放它的內(nèi)存- 標(biāo)記清理、引用計(jì)數(shù)垃圾回收詳細(xì)以及面試
- 性能
手動(dòng)解除引用灸叼,即設(shè)為null神汹,能確保下次垃圾回收時(shí)被成功回收而非馬上被回收- 函數(shù)內(nèi)局部變量會(huì)自動(dòng)被解除引用
- 由于let和const以塊(而非函數(shù))為作用域,可能會(huì)更早地接觸引用從而回收
- 隱藏類(lèi)的利用
-
內(nèi)存泄露(待辦)https://www.cnblogs.com/princeness/p/11664978.html
內(nèi)存泄露是指你用不到(訪(fǎng)問(wèn)不到)的變量古今,依然占居著內(nèi)存空間屁魏,不能被再次利用起來(lái)。
在某些環(huán)境中沧卢,這個(gè)閉包會(huì)導(dǎo)致內(nèi)存泄露蚁堤,即largeObject不能被及時(shí)回收
function outer() {
var largeObject = LargeObject.fromSize('100MB');
return function() {
console.log('inner');
};
}
var inner = outer();
遺留問(wèn)題:閉包為什么能會(huì)使內(nèi)存常駐,為什么能解決這里最后for循環(huán)的問(wèn)題