原始值和引用值
除了object外的變量都是原始值,引用值就是對象,對象實際上保存在內存空間,而js不允許訪問內存空間,因此在對對象進行任何操作時,操作的就是這個引用(reference)
- 用new時有區(qū)別
let name1 = "lpj";
let name2 = new String("lpj")'
name1.age = 19;
name2.age = 19;
console.log(name1.age);//undefined name1類型為string
console.log(name2.age);//19 name2類型為object
對象的“復制”
把引用值從一個變量賦給另一個變量時,其儲存的值也會復制,區(qū)別在于,這個值是指向這個對象的指針傳參只傳值不傳引用
function setName(obj){
obj.name = "lpj"
obj = new Object({
name:"hjy"
})
}
let person = Object()
setName(person)
console.log(person.name)//lpj而非hjy
在函數(shù)內部 obj和person都指向同一個對象,obj.name = "lpj"可以成功對這個對象進行操作,但是obj = new Object后,obj會被設置為一個新的引用值(新指針值),而非把這個引用指向一個新對象,這說明了傳參時不會傳引用,而只是傳了個指針值。換句話說,跟c++不同,c++傳一個數(shù)組變量進來,然后清空,那就是直接清空了。
上下文和作用域鏈 P89
變量或函數(shù)的上下文(即作用域)決定了他們能訪問哪些數(shù)據(jù)以及他們的行為
每個上下文都有一個關聯(lián)的變量對象,這個上下文中的所有變量和函數(shù)都存在這個對象上,這個以一定順序排列鏈接變量對象的集合就稱為作用域鏈,當前作用域的變量對象始終在鏈的最前
這樣就可以按順序去進入各個作用域的變量對象,從而訪問數(shù)據(jù)。
舉個例子說明作用域鏈規(guī)則
簡單來說:變量對象就像一個個車間,里面按順序裝著不同機器和原料
(如果是全局變量對象Windows的話,那就是總工廠,各種車間(函數(shù)、對象)和各種總工廠原料(全局變量)都算是這個工廠的機器/原料(屬性))
作用域鏈就像一條單向傳送帶連接不同車間,從小車間連向大車間最終連向總工廠
函數(shù)在創(chuàng)建和執(zhí)行時發(fā)生了什么?待辦什么是context,https://blog.csdn.net/konglingyuan/article/details/51441829
- 創(chuàng)建時:創(chuàng)建Function對象的內部屬性[[scope]],包含了一個函數(shù)當前作用域中對象的集合,即當前作用域的變量對象(是嗎),這個集合就是
函數(shù)的作用域鏈
它決定哪些數(shù)據(jù)可以被函數(shù)所訪問,它將把自己完全復制到執(zhí)行環(huán)境的作用域鏈中
- 執(zhí)行時:為函數(shù)創(chuàng)建一個執(zhí)行環(huán)境(execution context)內部對象
該對象與函數(shù)一一對應,會重復創(chuàng)建,執(zhí)行完畢即銷毀 - 為執(zhí)行環(huán)境初始化作用域鏈,初始化為當前函數(shù)的[scope]](即
函數(shù)的作用域鏈)的對象
注意 這里的作用域鏈不是上面的
函數(shù)的作用域鏈,而是屬于環(huán)境的,用于解析標識符
至此,活動對象創(chuàng)建完畢,成為函數(shù)運行時的一個變量對象
作用域鏈增強
指原本作用鏈前端對應的變量對象被換成了別的變量對象
try/catch的catch(創(chuàng)建新的變量對象)以及with語句(挪動變量對象到最前端)-
變量的作用域聲明
- var
在函數(shù)里var name,外面訪問不到,因為這個變量被添加到這個函數(shù)上下文的變量對象當中了但是如果不var,直接寫name,會自動添加為全局變量,放在全局變量對象當中- 提升(有點抽象)
var name = "lpj"等價于name = "lpj"; var name
也就是說 var在執(zhí)行的時候,這個聲明會被提升到頂端(函數(shù)頂端或全局頂端),但是這個賦值卻不會 舉例:
- 提升(有點抽象)
- var
console.log(name)//undefined
var name = 'lpj'//聲明被提升 但是賦值沒被提升
let
塊作用域:指最近的一堆{}就是一個塊,這解釋了為什么使用let可以防止for語句的i泄露出去標識符查找 P93
就是指沿著作用域鏈搜索這個變量的過程,如果在當前作用域找到了color = ''blue''查找即停止,在父級的color = "green"就不會生效
內存與性能P95
- 垃圾回收
每隔一段時間判定哪個變量不會再使用了,就釋放它的內存- 標記清理、引用計數(shù)垃圾回收詳細以及面試
- 性能
手動解除引用,即設為null,能確保下次垃圾回收時被成功回收而非馬上被回收- 函數(shù)內局部變量會自動被解除引用
- 由于let和const以塊(而非函數(shù))為作用域,可能會更早地接觸引用從而回收
- 隱藏類的利用
-
內存泄露(待辦)https://www.cnblogs.com/princeness/p/11664978.html
內存泄露是指你用不到(訪問不到)的變量,依然占居著內存空間,不能被再次利用起來。
在某些環(huán)境中,這個閉包會導致內存泄露,即largeObject不能被及時回收
function outer() {
var largeObject = LargeObject.fromSize('100MB');
return function() {
console.log('inner');
};
}
var inner = outer();
遺留問題:閉包為什么能會使內存常駐,為什么能解決這里最后for循環(huán)的問題

