【JS學習筆記】第四章變量调违、作用域和內(nèi)存問題

JS 變量松散類型的本質窟哺,決定了變量只是在特定時間保存特定值的一個名字而已,而不存在定義某個變量的數(shù)據(jù)類型的規(guī)則技肩,因此變量的值及其數(shù)據(jù)類型可以在腳本的生命周期內(nèi)發(fā)生改變且轨。

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

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

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

  • 引用類型的值是保存在內(nèi)存中的對象。js 不允許直接訪問內(nèi)存中的位置玷过,也就是不能直接操作對象的內(nèi)存空間爽丹。因此筑煮,在操作對象時,是在操作對象的引用粤蝎,而不是實際的對象真仲。

動態(tài)屬性

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

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

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

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

復制變量值

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

復制基本類型的值時贿条,會在變量對象上創(chuàng)建一個新值增热,然后把該值復制到為新變量分配的位置上

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

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

IMG_8066.JPG

傳遞參數(shù)

ECMAScript 中所有函數(shù)的參數(shù)都是按值傳遞的。
在向參數(shù)傳遞基本類型的值時桅狠,被傳遞的值會被復制給一個局部變量(即命名參數(shù)讼载,arguments對象中的一個元素)轿秧。
在向參數(shù)傳遞引用類型的值時,會把值在內(nèi)存中的地址復制給一個局部變量咨堤,因此這個局部變量的變化會反映在函數(shù)的外部菇篡。

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

檢測類型

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

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

執(zhí)行環(huán)境及作用域

執(zhí)行環(huán)境咐容,execution context,簡稱環(huán)境蚂维,定義了變量或函數(shù)有權訪問的其他數(shù)據(jù)戳粒,決定了各自的行為。每個執(zhí)行環(huán)境都有一個與之關聯(lián)的變量對象(variable object)鸟雏,環(huán)境中定義的所有變量和函數(shù)都保存在這個對象中享郊。編寫代碼無法訪問這個對象,但解析器在處理數(shù)據(jù)時會在后臺使用它孝鹊。

全局執(zhí)行環(huán)境是最外圍的一個執(zhí)行環(huán)境炊琉。在web瀏覽器中,全局執(zhí)行環(huán)境是Window對象又活,所有全局變量和函數(shù)都是作為 Window的屬性和方法創(chuàng)建的苔咪。某個執(zhí)行環(huán)境中所有代碼執(zhí)行完畢后,該執(zhí)行環(huán)境被銷毀柳骄,保存在其中的所有變量和函數(shù)定義也隨之銷毀团赏。

每個函數(shù)都有自己的執(zhí)行環(huán)境。當執(zhí)行流進入一個函數(shù)時耐薯,函數(shù)的環(huán)境就會被推入到一個環(huán)境棧中舔清,函數(shù)執(zhí)行之后,棧將其環(huán)境彈出曲初,把控制權返回給之前的執(zhí)行環(huán)境体谒。ECMAScript程序中的執(zhí)行流正是由這個方便的機制控制著。

當代碼在一個環(huán)境中執(zhí)行時臼婆,會創(chuàng)建變量對象的一個作用域鏈(scope chain)抒痒。用途是保證對執(zhí)行環(huán)境有權訪問的所有變量和函數(shù)的有序訪問。作用域鏈前端颁褂,是當前執(zhí)行代碼所在環(huán)境的變量對象故响。如果這個環(huán)境是函數(shù)傀广,則將其活動對象(activation object)作為變量對象〔式欤活動對象最開始只包含一個變量伪冰,即arguments對象。作用域鏈中下一個變量對象來自包含(外部)環(huán)境惨缆,再下一個變量對象在來自下一個包含環(huán)境糜值,最后是全局執(zhí)行環(huán)境。

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

延長作用域鏈

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

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

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

沒有塊級作用域

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

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

但在js中蕾各,if語句中的變量聲明會將變量添加到當前的執(zhí)行環(huán)境扒磁,這里是全局環(huán)境。

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

alert(i);//10

對于塊級作用域的語言來說式曲,for語句初始化變量的表達式所定義的變量妨托,只會存在于循環(huán)的局部環(huán)境。而對于JS來說吝羞,變量i即使在for循環(huán)結束后兰伤,也依舊會存在于循環(huán)外部的執(zhí)行環(huán)境中。

  1. 變量聲明
    使用var聲明的變量會自動被添加到被接近的環(huán)境中钧排,在函數(shù)內(nèi)部敦腔,最接近的環(huán)境就是函數(shù)的局部環(huán)境。下面例子中恨溜,sum被var聲明符衔,添加到add()函數(shù)的局部環(huán)境中,因此在全局環(huán)境中訪問時糟袁,是導致錯誤柏腻。這里如果省略var,則sum會被添加到全局環(huán)境中系吭。
function add(num1,num2) {
    var sum =num1 + num2 ;
    return sum;
}
var result = add(10,20);//30
alert(sum); //導致錯誤

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

垃圾收集

js具有自動垃圾收集機制肯尺,不用手動跟蹤內(nèi)存的使用情況沃缘。

函數(shù)中的局部變量只在函數(shù)執(zhí)行的過程中存在,因此在函數(shù)執(zhí)行完畢后则吟,對其打上標記槐臀,將來回收其內(nèi)存。

標記清除

mark-and-sweep
當變量進入環(huán)境時(例如在函數(shù)中聲明一個變量)氓仲,將這個變量標記為進入環(huán)境水慨,而當變量離開環(huán)境時,則將其標記為離開環(huán)境敬扛。

垃圾收集器在允許的時候回給存儲在內(nèi)存中的所有變量都加上標記晰洒,然后去掉環(huán)境中的變量以及被環(huán)境中變量引用的變量的標記,在此之后啥箭,再被加上標記的變量將被視為準備刪除的變量谍珊。最后,垃圾收集器完成內(nèi)存清楚工作急侥,銷毀那些帶標記的值回收其占用的內(nèi)存空間砌滞。

另一種是引用計數(shù)

性能問題

當環(huán)境中存在256個變量,4096個對象坏怪,64K的字符串贝润,任意一種都會觸發(fā)垃圾回收機制,但如果環(huán)境中一直都有這么多變量存在铝宵,那么垃圾回收器會一直工作打掘。

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

管理內(nèi)存

JS中惜纸,分配給web瀏覽器的可用內(nèi)存數(shù)量通常比分配給桌面應用程序的少叶撒,處于安全考慮。內(nèi)存限制問題不僅會影響給變量分配內(nèi)存問題耐版,還會影響調用棧以及在一個線程中能夠同時執(zhí)行的語句數(shù)量祠够。

因此,為了讓頁面獲得更好的性能粪牲,我們需要占用最少的內(nèi)存古瓤,優(yōu)化內(nèi)存占用,只為執(zhí)行中的代碼保存必要的數(shù)據(jù)。一旦數(shù)據(jù)不再有用落君,可將其值設置為null釋放其引用穿香,這個做法叫做解除引用(dereferencing)。一般用于釋放全局變量的內(nèi)存绎速,因為局部變量在離開執(zhí)行環(huán)境時自動被解決引用皮获。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市纹冤,隨后出現(xiàn)的幾起案子洒宝,更是在濱河造成了極大的恐慌,老刑警劉巖萌京,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件雁歌,死亡現(xiàn)場離奇詭異,居然都是意外死亡枫夺,警方通過查閱死者的電腦和手機将宪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來橡庞,“玉大人较坛,你說我怎么就攤上這事“亲睿” “怎么了丑勤?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吧趣。 經(jīng)常有香客問我法竞,道長,這世上最難降的妖魔是什么强挫? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任岔霸,我火速辦了婚禮,結果婚禮上俯渤,老公的妹妹穿的比我還像新娘呆细。我一直安慰自己,他們只是感情好八匠,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布絮爷。 她就那樣靜靜地躺著,像睡著了一般梨树。 火紅的嫁衣襯著肌膚如雪坑夯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天抡四,我揣著相機與錄音柜蜈,去河邊找鬼仗谆。 笑死,一個胖子當著我的面吹牛跨释,可吹牛的內(nèi)容都是我干的胸私。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼鳖谈,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了阔涉?” 一聲冷哼從身側響起缆娃,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瑰排,沒想到半個月后贯要,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡椭住,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年崇渗,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片京郑。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡宅广,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出些举,到底是詐尸還是另有隱情跟狱,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布户魏,位于F島的核電站驶臊,受9級特大地震影響,放射性物質發(fā)生泄漏叼丑。R本人自食惡果不足惜关翎,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鸠信。 院中可真熱鬧纵寝,春花似錦、人聲如沸症副。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凑兰。三九已至挠进,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辕坝,已是汗流浹背窍奋。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人琳袄。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓江场,卻偏偏與公主長得像,于是被迫代替她去往敵國和親窖逗。 傳聞我的和親對象是個殘疾皇子址否,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

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