您好,登錄后才能下訂單哦!
小編給大家分享一下Javascript中作用域的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
我們主要來看看Javascript中變量作用域的問題。主要涉及以下內容 :
參數傳遞的問題
什么是作用域和作用域鏈
塊級作用域
延長作用域鏈
參數傳遞的問題
在Javascript中所有的參數傳遞都是按值傳遞的。也就是說把函數外部的值復制給函數內部的參數,就和把值從一個變量復制到另一個變量一樣。基本類型值的傳遞如同基本類型變量的復制一樣,而引用類型值的傳遞,就如同引用類型變量的復制一樣。
—— 《Javascript 高級程序設計》 第三版
function addTen(num) { num += 10; return num; } var count = 20; var result = addTen(count); alert(count) // 20 alert(result) // 30
我想關于值類型的傳遞應該很簡單,所以我們就不多說了,重點來看看引用類型的值傳遞。
function setName(person) { person.name = "Jesse"; } var person = new Object(); setName(person); alert(person.name); //Jesse
這個函數把我們外部對象的值也一起改變了,這一點和C#也是一樣的。因為函數里面的person所指向的地址和外部person所指向的地址是一樣的。下面的行為也是和C#一樣的,即如果在函數內容把參數指向另外一個對象,不會對外部對象產生影響 。
function setName(person) { person.name="Jesse" person = new Object(); person.name = "Another Jesse"; } var person = new Object(); setName(person); alert(person.name); //Jesse
關于引用類型的拷貝,給初學者一張圖解。
在堆中分配一塊空間給person對象,并在棧中保存person在堆中的址址引用
復制堆中person的地址引用給person2(同樣是在棧中)
new Person()再次在堆中分配一塊空間給person2對象,然后將棧中person2指向這個新的地址。
以后對person2的更改不會對person產生影響
什么是作用域和作用域鏈
我們知道在JavaScript中有局部變量和全局變量,某個函數里面的局部變量不能在另一個函數中被訪問(暫且避開閉包不談)。這就是作用域起的作用,因為變量只在它所在的那個函數里面起作用。
每一個函數都有自己的執行環境,而每一個執行環境都有一個與之相關聯的變量對象, 這個環境中所有變量和函數就保存在這個變量中。除了函數有自己的執行環境以外,我們還有一個最大的全局執行環境,而我們所熟知的window就是這個全局執行環境的變量對象,因為所有的全局變量和函數都是作為window的屬性和方法創建的。每個環境中的所有代碼執行完后,該環境被隨之銷毀,保存在其中的所有變量和函數也隨之銷毀。對于全局執行環境來說,關閉瀏覽器或者退出頁面,那么這個全局的執行環境也就被銷毀了。
但是,我在這個函數里面是不是只能訪問這個函數里面的變量呢?也許大家都知道,還有全局變量,全局變量可以被任意函數(Javascript沒有像public, private, protected 這樣的關鍵字),或者任意引入到頁面的js訪問到。這個就是我們常說的作用域鏈。作用域鏈的作用就是保證對執行環境有權訪問的所有變量和函數進行有序訪問。為什么說有序訪問呢? 來看一看下面這段代碼:
var color = "blue"; function alertColor() { var color = "red"; alert(color); } alertColor(); // red alert(color); // blue
大家知道如果局部變量和全局變量同名的話,全局變量會被覆蓋,但是也不是真正的覆蓋,只是在當前這個函數里面被覆蓋而已,我們在外部依舊可以正常使用的。這里就涉及到一個執行環境有序訪問的問題。
作用域鏈的最前端永遠是當前執行代碼所在環境的變量對象,對于我們的alertColor而言,就是它自己的活動對象。 所有函數的活動對象都包含一個初始值,那就是我們的arguments。而作用域鏈的下一個對象,來自包含的外部環境,一直延續到全局環境。所有函數的作用域鏈都可能延續到全局環境,這就是為什么全局變量可以在所有函數中訪問的原因,并不是因為它叫全局變量,所以它就可以在所有函數中訪問:) 并且,全局執行環境的環境變量始終是作用域鏈的最后一個對象。
我們來看個復雜一點的例子:
var color = "blue"; function changeColor(){ var anotherColor = "red"; function swapColors(){ var tempColor = anotherColor; anotherColor = color; color = tempColor; // 這里面可以訪問到 color, anotherColor, tempColor } // 這里只能訪問到 anotherColor swapColors(); } // 這里只能訪問到color changeColor();
在上面的代碼中,我們有3個執行環境,全局環境、changeColor的局部執行環境和swapColors的局部執行環境。全局環境中只有一個變量color和一個函數changeColor()。changeColor中有一個變量anotherColor和一個函數swapColors(),但是它可以訪問到全局環境中的color。swapColors中有一個局部變量tempColor,該變量只不管是在changeColor還是全局環境中都不能被訪問到,然后在swapColors中可以訪問到其它兩個環境中的所有變量,因為另外兩個環境都是它的父執行環境。
我們可以發現,作用域鏈是由內向外擴展的,我們可以通過作用域訪問外部環境的變量和函數,但是外部環境中訪問不到內部環境的變量和函數。我們在swapColors中用到了全局變量color,但是它也不是一下子就找到color的,它有一個由內向外的查找過程:
在當前執行環境內尋找叫color的局部變量,沒有找到,向上升一級
在父級執行環境changeColor中去找叫color的變量,也沒有找到,再向上升一級
在changeColor的父級中找到了color變量,直接拿過來使用。
塊級作用域
因為有著塊級作用域(以花括號作為起始點)的存在,C#中這樣的代碼是編譯不通過的。
static void Main(string[] args) { for(var i=0;i<=10;i++) { Console.Write(i); } Console.Write(i); }
我們在for循環以外已經訪問不到i了。但是在Javascript情況就完全不一樣了。
for (var i = 0; i <= 10; i++) { // } alert(i); // 11
延長作用域鏈
我們上面說了,在Javascript中總共只有2種執行環境:全局和局部執行環境。但是我們可以用with和try-catch來延長作用域,由于平常使用場景較少,我們就拿with來舉個例子好了。
function buildUrl() { var qs = "?debug=true"; with(location){ var url = href + qs; } return url; }
在with的作用下,location這個變量被加到了作用域的最前端,所以所有location下的變量和方法都可以在with的這個范圍內訪問了。
以上就是我們要講的作用域的內容了,來總結一下吧:
值類型按值傳遞,引用類型按引用傳遞。傳遞的行業和用變量拷貝的行業是一樣的。
Javascript中有兩種執行環境:全局和局部(函數)
執行環境內有一個變量對象定義了該執行環境下能訪問的變量和函數
執行環境可以由內向外延伸一直延伸到全局的執行環境
Javascript沒有塊級作用域
以上是“Javascript中作用域的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。