摘要:具體說就是執行流進入下列任何一個語句時,作用域鏈就會得到加長語句的塊。如果局部環境中存在著同名的標識符,就不會使用位于父環境中的標識符訪問局部變量要比訪問全局變量更快,因為不用向上搜索作用域鏈。
基本類型和引用類型的值
ECMAscript變量包含 基本類型值和引用類型值
基本類型值值的是基本數據類型:Undefined, Null, Boolean, Number, String
引用類型值是保存在內存空間中的對象,與其他JavaScript不允許直接訪問內存中的位置,即不能直接操作對象的內存空間,在操作對象時,實際上是在操作對象的引用而不是實際的對象;為此,引用類型的值是按引用訪問的
在很多語言中,字符串以對象 的形式來表示,因此被認為是引用類型的,ECMAScript放棄了這一傳統
動態的屬性引用類型的值可以為其添加屬性和方法,也可以改變和刪除屬性和方法
基本類型值不行
var person = new Object(); person.name = "Nicholas"; alert(person.name); // "Nicholas" var person = "Nicholas"; person.age = 27; alert(person.age); // undefined復制變量值
在從一個變量復制向另一個變量復制值時,基本類型值和引用類型值存在不同
基本類型值會在變量對象上創建一個新值,然后把該值復制到為新變量分配的位置上,兩個變量可以參與任何操作而不會互相影響
引用類型也會復制一個副本放到新變量中,但這個副本實際上是一個指針,這個指針指向存儲在堆中的一個對象,復制操作結束后,兩個變量實際上將引用同一個對象,因此改變其中一個變量,就會影響另一個變量
var obj1 = new Object(); var obj2 = obj1; obj1.name = "Nicholas"; alert(obj2.name); // "Nicholas"傳遞參數
ECMAscript中所有函數的參數都是按值傳遞的,即把函數外部的值復制給函數內部的參數,就和把值從一個變量復制到另一個變量一樣
在向參數傳遞基本類型的值時,被傳遞的值會被復制給一個局部變量(即為命名參數,或者用ECMAScript的概念來說,就是函數的arguments對象中的一個元素)
在向參數傳遞引用類型的值時,會把這個值在內存中的地址復制給一個局部變量,因此這個局部變量的變化會反映在函數外部
可以把ECMAScript的參數想象成局部變量
// 參數num是函數的局部變量 // 調用這個函數時,變量count作為參數被傳遞給函數,是將count的值20復制給參數num // 在函數內部,參數num的值加上了10,但不會影響函數外部的count變量,count和num互不影響 function addTen(num) { num += 10; return num; } var count = 20; var result = addTen(count); alert(count); // 20, 沒有變化 alert(result); // 30
// 以下為個人理解,原著表述不清楚不能直觀理解 // 傳遞給參數obj的實際上是指向person對象內存地址(指針),是將地址復制了一個副本賦值給了參數obj // 當在函數內部為obj添加name屬性后,函數內部根據地址操作了內存中的相應對象,函數外部的person也將有反映 // 因為person指向的對象在堆內存中只有一個,而且是全局對象 function setName(obj) { obj.name = "Nicholas"; } var person = new Object(); setName(person); alert(person.name); // "Nicholas" // 下列代碼,直覺認為會alert出"Greg",但卻是"Nicholas" // 因為傳遞給參數obj的只是指針的副本,當函數內重新給obj賦值的時候,實際上是將一個新的Object對象的指針賦給obj // 此時操作obj影響的是新的Object對象,而person對象不受影響 // obj指向的新Object對象在函數執行完后會立即銷毀 function setName(obj) { obj.name = "Nicholas"; obj = new Object(); obj.name = "Greg"; } var person = new Object(); setName(person); alert(person.name); // "Nicholas"檢測類型
typeof操作符是確定一個變量是不是基本數據類型的最佳工具
null和對象 typeof都會返回"object"
檢測引用類型的值,instanceof操作符是最佳工具
根據規定,所有引用類型的值都是Object的實例。因此在檢測一個引用類型值和Object構造函數時,instanceof操作符始終返回true。如果使用instanceof操作符檢測基本類型的值,返回false,因為基本類型不是對象
typeof 檢測函數會返回"function".在Safari 5 及 之前版本 Chrome 7 及 之前版本中使用typeof檢測正則表達式,也返回"function",ECMA-262規定任何在內部實現[[call]]方法的對象都應該在應用typeof操作符時返回"function",由于上述瀏覽器中的正則表達式也實現了這個方法,因此對正則表達式應用typeof會返回"function"。其他瀏覽器返回"object".
執行環境及作用域執行環境(execution context,為簡單起見,有時也成為“環境”)是JavaScript中最為重要的一個概念
每個執行環境都有一個與之關聯的變量對象(variable object),環境中定義的所有變量和函數都保存在這個對象中。
雖然編寫的代碼無法訪問這個對象,但解析器在處理數據時會在后臺使用它
全局執行環境是最外圍的一個執行環境。在web瀏覽器中,全局執行環境被認為是window對象,因此所有全局變量和函數都是作為window對象的屬性和方法創建的
某個執行黃精中的所有代碼執行完畢后,該環境被銷毀,保存在其中的所有變量和函數定義也隨之銷毀(全局執行環境直到應用程序退出——例如關閉網頁或瀏覽器——時才會被銷毀)
每個函數都有自己的執行環境。當執行流進入一個函數時,函數的環境就會被推入一個環境棧中,函數執行完畢后,棧將其環境彈出,把控制權返回給之前的執行環境
當代嗎在一個環境中執行時,會創造變量對象的一個作用域鏈(scope chain)。作用域鏈的用途,是保證對執行環境有權訪問的所有變量和函數有序的訪問
作用域鏈最前端始終是當前執行的代碼所在環境的變量對象,如果這個環境是函數,則將其活動對象(activation object)作為變量對象,活動對象在最開始時只包含一個變量,即arguments對象(這個對象在全局環境中是不存在的)。作用域鏈的最后一個對象始終都是全局執行環境的變量對象
標識符解析是沿著作用域鏈一級一級的搜索標識符的過程,從最前端開始,然后逐級向后回溯,直到找到標識符為止(找不到通常會發生錯誤)
// 函數changeColor()的作用域鏈包含兩個對象: // 它自己的變量對象(其中定義著arguments對象)和全局環境的變量對象 var color = "blue"; function changeColor() { if (color === "blue") { color = "red"; } else { color = "blue"; } } changeColor(); alert("color is now " + color); // "red"延長作用域鏈
有些語句尅在作用域鏈的前端臨時增加一個變量對象,該變量對象會在代碼執行后被移除。具體說就是執行流進入下列任何一個語句時,作用域鏈就會得到加長
try-catch 語句的catch塊。catch語句會創建一個新的變量對象,其中包含的是被拋出錯誤對象的聲明
with語句,會將制定的對象添加到作用域鏈中
沒有塊級作用域在其他類C語言中,由花括號封閉的代碼都有自己的作用域,但JavaScript不會
if (true) { var color = "blue"; } alert(color); // "blue"
聲明變量,使用var聲明的變量會自動被添加到最接近的環境中,在函數內部,就是函數的局部環境
查詢標識符,逐級向上查詢,如果存在一個局部的變量定義,則搜索停止。如果局部環境中存在著同名的標識符,就不會使用位于父環境中的標識符
var color = "blue"; function getColor() { var color = "red"; return color } alert(getColor()); // "red" alert(color); // "blue"
訪問局部變量要比訪問全局變量更快,因為不用向上搜索作用域鏈。不過JavaScript引擎在優化標識符查詢方面做的不錯,因此這個差別在將來恐怕就可以忽略不計了
垃圾收集JavaScript具有自動垃圾收集機制,即,執行環境會負責管理代碼執行過程中使用的內存
這種機制很簡單,找出那些不再繼續使用的變量,然后釋放其占用的內存,為此垃圾收集器會按照固定的時間間隔(或代碼執行中預定的收集時間),周期性的執行這一操作
標記清除(mark-and-sweep)標記清除是JavaScript中最常用的垃圾收集方式
當變量進入環境,就標記“進入環境”。從邏輯上講,永遠不能釋放進入環境的變量所占用的內存。而當變量離開環境時,則將其標記為離開環境
引用計數 (reference counting)當聲明了一個變量并將一個引用類型值賦給變量時,則這個值的引用次數就+1
當引用了這個值的變量又被賦給了其他值,則這個值的引用次數-1
當這個值的次數變成0時,就可以將其占用的內存空間回收
當兩個對象的屬性互相引用對方時,陷入死循環,將無法回收,為此Netscape在navigator 4.0中放棄了該方案
管理內存一旦數據不再有用,最好通過將其值設置為null來釋放引用——解除引用(dereferencing),這一做法適用于大多數全局變量和全局對象的屬性,而局部變量會自動被解除引用
解除引用不會立即觸發回收機制,而是讓其脫離執行環境,以便下一次回收時釋放內存
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/104169.html
摘要:定義函數表達式的方式有兩種函數聲明。不過,這并不是匿名函數唯一的用途。可以使用命名函數表達式來達成相同的結果閉包匿名函數和閉包是兩個概念,容易混淆。匿名函數的執行環境具有全局性,因此其對象通常指向通過改變函數的執行環境的情況除外。 定義函數表達式的方式有兩種: 函數聲明。它的重要特征就是 函數聲明提升(function declaration hoisting) 即在執行代碼之前會...
摘要:表示應該立即下載腳本,但不應妨礙頁面中的其他操作可選。表示通過屬性指定的代碼的字符集。表示腳本可以延遲到文檔完全被解析和顯示之后再執行。實際上,服務器在傳送文件時使用的類型通常是,但在中設置這個值卻可能導致腳本被忽略。 第1章 JavaScript 簡介 雖然JavaScript和ECMAScript通常被人們用來表達相同的含義,但JavaScript的含義比ECMA-262要多得多...
摘要:于是我就先把這本薄的經典書語言精粹修訂版豆瓣讀書本書簡介總共章,除去附錄,才頁,讀完并記錄了一些筆記。讀書筆記還可以分享給別人看。編程語言第版定義了的標準。程序檢查時丟棄值為函數的屬性。 之前看到這篇文章,前端網老姚淺談:怎么學JavaScript?,說到怎么學習JavaScript,那就是看書、分析源碼。10本書讀2遍的好處,應該大于一本書讀20遍。看書主動學習,看視頻是被動學習???..
摘要:具體來說就是當執行流進入下列任何一個語句時,作用域鏈就會得到加長語句的塊和語句。這兩個語句都會在作用域鏈的前端添加一個變量對象。對來說,會將指定的對象添加到作用域鏈中。 1. 基本類型和引用類型的值 JavaScript變量可以用來保存兩種類型的值:基本類性值和引用類性值。基本類型值源自以下5種基本數據類型:Undefined、Null、Boolean、Number和String。基本...
摘要:引用類型的值對象是引用類型的一個實例。引用類型是一種數據結構,用于將數據和功能組織在一起。對數組中的每一項運行給定函數,如果該函數對任一項返回,則返回。組零始終代表整個表達式。所以,使用非捕獲組較使用捕獲組更節省內存。 引用類型的值(對象)是引用類型的一個實例。 引用類型是一種數據結構,用于將數據和功能組織在一起。它同行被稱為類,但這種稱呼并不妥當,盡管ECMAScript從技術上講...
閱讀 2733·2023-04-25 14:15
閱讀 2685·2021-11-04 16:11
閱讀 3385·2021-10-14 09:42
閱讀 434·2019-08-30 15:52
閱讀 2819·2019-08-30 14:03
閱讀 3536·2019-08-30 13:00
閱讀 2105·2019-08-26 11:40
閱讀 3301·2019-08-26 10:25