摘要:作用域鏈是保證對執(zhí)行環(huán)境有權訪問的所有變量和函數(shù)的有序訪問。如上,包含的作用域鏈包含它自己的變量對象和全局環(huán)境的變量對象,為什么能在函數(shù)內訪問,這就是通過作用域鏈找的。
前言
JavaScript的變量類型是弱類型的,在特定的時間內保存一個特定的值,變量的值和數(shù)據(jù)類型可以在腳本的生命周期內隨意改變。
JavaScript包含兩種不同類型的值:基本類型和引用類型?;绢愋椭傅氖呛唵蔚臄?shù)據(jù)段,而引用類型指的是那些由多個值構成的對象。
基本數(shù)據(jù)類型Number,String,Boolean,Null,Undefined這五種基本類型數(shù)據(jù)是按值訪問的,因為可以操作在變量中實際的值。
引用類型是保存到內存中的對象,不允許直接訪問內存中的位置,也就是說不能直接操作對象的內存空間。在操作對象的時候,實際上操作的是對象的引用。所以,引用類型是按引用訪問的。(但是在為對象添加屬性的時候,實際上操作的是實際的對象)
動態(tài)添加屬性
定義基本類型和引用類型值得方式是類似的,都是創(chuàng)建一個變量然后為該變量賦值。但是當值存入變量后,不同類型的值執(zhí)行的操作則有些區(qū)別。先看下對引用類型的值得操作:
var person = new Object() person.name = "nicholas" alert(person.name) //"nicholas"
如上,創(chuàng)建一個對象并保存到變量person中,然后為該對象添加一個name屬性且賦值為“nicholas”,最后可以訪問這個新屬性。
假如我們給基本類型的值添加屬性,如下:
var person = "good job" person.name = "Nike" alert(person.name) //"undefined"
雖然我們看到沒有出現(xiàn)任何報錯,但是這是不符合規(guī)范的。
復制變量值
上面說的是給基本類型和引用類型分別添加屬性的區(qū)別。接下來,我們從一個變量向另外一個變量復制基本類型值和引用類型值看看有什么區(qū)別。
先看基本類型的,從一個變量向另外一個變量復制:
var a = "China NO.1" var b = a alert(b) //"China NO.1"
如上,輸出b的時候的值和a是一模一樣的,但是兩者是完全獨立的。這是因為從a復制到b的時候,會在變量對象上創(chuàng)建一個新值,然后把這個值賦值給b。
在看引用類型,當從一個變量向另一個變量復制引用類型值得時候,同樣會將存在變量a中的值復制一份放到b中,但是不同的是,這個值得副本是一個指針,這個指針指向存在堆內存中的一個對象。當結束復制后,這兩個變量實際上引用的是一個對象。
var a = new Object() var b = a a.name = "nike" alert(b.name) //"nike"
如上,因為a和b都是引用同一個堆內存中的地址,所以當給a添加一個name屬性后,b也可以訪問到這個屬性。
傳遞參數(shù)
JavaScript中所有函數(shù)的參數(shù)都是按值傳遞的。也就是說把函數(shù)外部的值復制給函數(shù)內部的參數(shù),就和把值從一個變量復制到另一個變量一樣。
向參數(shù)傳遞基本類型值得時候,被傳遞的值會被復制給一個局部變量。在向參數(shù)傳遞引用類型值得時候,會將這個值在內存中的引用地址復制給這個局部變量,因此這個局部變量的變化會反映在函數(shù)的外部,
先看一個基本類型值傳遞給函數(shù)參數(shù)的例子:
function add(num){ num += 10 return num } var count = 20 var result = add(count) alert(count) //20 alert(result) //30
接下來用引用類型的值舉個例子:
function setName(obj){ obj.name = "nike" } var person = new Object() setName(person) alert(person.name) //"nike"
上面的例子中,首先創(chuàng)建一個對象保存到person中,然后將person傳到setName中,person的值會被復制給obj。所以obj現(xiàn)在和person引用的是同一個對象(即這個變量是按值傳遞的),obj也會按引用訪問同一個對象。在來看一個例子:
function setName(obj){ obj.name = "nike" obj = new Object() obj.name = "green" } var person = new Object() setName(person) alert(person.name)//"nike"
這個例子和上面的區(qū)別就是為obj又重新定義了一個對象,然后為這個新對象定義了一個不同值得name屬性。如果person是按引用傳遞的,nameperson就會被修改為指向name屬性值為’green‘的新對象。但是并沒有這樣,實際上當函數(shù)在內部重寫obj的時候,這個比那里引用的就是一個局部對象了。而這個局部對象會在函數(shù)執(zhí)行完畢后銷毀。
檢測類型
typeof操作符是一個確定變量是String,Number,Boolean,Null,Undefined的最佳工具。
var s = "abc" var b = true var n = 22 var nu = null var u = "undefined" typeof s //string typeof b //boolean typeof n //number typeof nu //object typeof u //undefined
還有一個instanceof操作符,通過它我們可以判斷是什么類型的對象:
//格式 變量 instanceof constructor
如果constructor在該對象的原型鏈上,那么就會返回true。
2.執(zhí)行環(huán)境和作用域執(zhí)行環(huán)境定義了變量或者函數(shù)有權訪問的其他數(shù)據(jù),決定了它們各自的行為。每個執(zhí)行環(huán)境都有一個與之相關的變量對象,變量對象中保存該執(zhí)行環(huán)境中的所有變量和函數(shù)。在代碼層面,我們是無法訪問到這個變量對象,但是JS引擎在處理的時候會用到它。
全局執(zhí)行環(huán)境是最外層的一個執(zhí)行環(huán)境,在瀏覽器中,全局執(zhí)行環(huán)境被認為是window對象,因為所有全局變量和函數(shù)都是作為window對象的屬性和方法創(chuàng)建的。
注意:某個執(zhí)行環(huán)境中所有代碼執(zhí)行完畢后,該執(zhí)行環(huán)境會被銷毀,保存在其中的所有變量和函數(shù)定義也會被銷毀。全局環(huán)境是在應用退出后才被銷毀。
每個函數(shù)都會有自己的執(zhí)行環(huán)境,當執(zhí)行流進入一個函數(shù)時,該執(zhí)行環(huán)境被推入到一個環(huán)境棧中,在執(zhí)行完畢后會彈出,將控制權返回給之前的執(zhí)行環(huán)境,JavaScript中的執(zhí)行流正是由這個機制控制。
當代碼在一個執(zhí)行環(huán)境中運行時,會創(chuàng)建變量對象的一個作用域鏈。作用域鏈是保證對執(zhí)行環(huán)境有權訪問的所有變量和函數(shù)的有序訪問。(注意這里說的有權訪問)作用域鏈的前端,始終都是當前執(zhí)行的代碼所在環(huán)境的變量對象。如果這個執(zhí)行環(huán)境是一個函數(shù),則將其活動對象作為變量對象。活動對象在最開始的時候只包含一個arguments對象。作用域鏈的下一個變量對象是來自包含(外部)的執(zhí)行環(huán)境。再下一個變量對象則來自于下一個包含環(huán)境,以此類推,最外層的變量對象來自于全局執(zhí)行環(huán)境。
標識符的解析過程也就是沿著作用域鏈一級一級的搜索,直到找到標識符為止,否則就會發(fā)生錯誤。
var color = "blue" function changeColor() { if(color == "blue"){ color = "red" }else { color = "blue" } } changeColor()
如上,changeColor包含的作用域鏈包含它自己的變量對象和全局環(huán)境的變量對象,為什么能在函數(shù)內訪問color,這就是通過作用域鏈找的。
在JavaScript中,執(zhí)行環(huán)境會負責管理代碼執(zhí)行過程中使用的內存。當不再使用的變量,就會釋放其占用的內存,垃圾收集器會按照固定的時間間隔去執(zhí)行這個操作。
JavaScript中函數(shù)的局部變量只有在函數(shù)執(zhí)行的過程中存在,在執(zhí)行的過程中會為局部變量在?;蛘叨褍却嬷蟹峙漤憫目臻g,以便存儲它們的值,然后在函數(shù)中使用這些變量,直至函數(shù)執(zhí)行結束。
關于垃圾回收的方法有標記清除,引用計數(shù)這兩個方法,對于其原理有興趣的同學可以去研究研究~
總結:今天主要講了基本數(shù)據(jù)類型和引用數(shù)據(jù)類型的區(qū)別;關于函數(shù)參數(shù)是值傳遞的證明;函數(shù)的執(zhí)行環(huán)境,變量對象以及作用域鏈的形成。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/91966.html
摘要:內存泄露內存泄露概念在計算機科學中,內存泄漏指由于疏忽或錯誤造成程序未能釋放已經不再使用的內存。判斷內存泄漏,以字段為準。 本文是 重溫基礎 系列文章的第二十二篇。 今日感受:優(yōu)化學習方法。 系列目錄: 【復習資料】ES6/ES7/ES8/ES9資料整理(個人整理) 【重溫基礎】1-14篇 【重溫基礎】15.JS對象介紹 【重溫基礎】16.JSON對象介紹 【重溫基礎】1...
摘要:系列目錄復習資料資料整理個人整理重溫基礎篇重溫基礎對象介紹重溫基礎對象介紹重溫基礎介紹重溫基礎相等性判斷本章節(jié)復習的是中的關于閉包,這個小哥哥呀,看看。這里隨著閉包函數(shù)的結束,執(zhí)行環(huán)境銷毀,變量回收。 本文是 重溫基礎 系列文章的第十九篇。今日感受:將混亂的事情找出之間的聯(lián)系,也是種能力。 系列目錄: 【復習資料】ES6/ES7/ES8/ES9資料整理(個人整理) 【重溫基礎】...
摘要:作用域鏈的用途,是保證對執(zhí)行環(huán)境有權訪問的變量和函數(shù)的有序訪問。全局執(zhí)行環(huán)境始終是作用域鏈的最后一個對象。延長作用域鏈雖然執(zhí)行環(huán)境的類型只有兩種。 最近在忙于寫一個react+node的全棧博客demo,沒有時間更新文章。但是還是覺得這樣一忙起來不更新是不應該的。正好在空閑上下班地鐵上都會再去細讀js原生知識。所以打算整理、總結、系統(tǒng)性的分享給大家。 基本類型和引用類型 在ECMASc...
摘要:內部的稱為內部函數(shù)或閉包函數(shù)。過度使用閉包會導致性能下降。,閉包函數(shù)分為定義時,和運行時。循環(huán)會先運行完畢,此時,閉包函數(shù)并沒有運行。閉包只能取得外部函數(shù)中的最后一個值。事件綁定種的匿名函數(shù)也是閉包函數(shù)。而對象中的閉包函數(shù),指向。 閉包概念解釋: 閉包(也叫詞法閉包或者函數(shù)閉包)。 在一個函數(shù)parent內聲明另一個函數(shù)child,形成了嵌套。函數(shù)child使用了函數(shù)parent的參數(shù)...
摘要:本文是重溫基礎系列文章的第四篇。系列目錄復習資料資料整理個人整理重溫基礎語法和數(shù)據(jù)類型重溫基礎流程控制和錯誤處理重溫基礎循環(huán)和迭代本章節(jié)復習的是中的基礎組件之一,函數(shù),用來復用特定執(zhí)行邏輯。箭頭函數(shù)不能使用命令,即不能用作函數(shù)。 本文是 重溫基礎 系列文章的第四篇。今日感受:常懷感恩之心,對人對己。 系列目錄: 【復習資料】ES6/ES7/ES8/ES9資料整理(個人整理) 【重溫基...
閱讀 1045·2021-09-26 09:55
閱讀 3619·2021-09-24 10:30
閱讀 1408·2021-09-08 09:36
閱讀 2584·2021-09-07 09:58
閱讀 626·2019-08-30 15:56
閱讀 796·2019-08-29 18:32
閱讀 3687·2019-08-29 15:13
閱讀 1864·2019-08-29 13:49