欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Javascript基礎(chǔ)回顧之(二) js作用域

 更新時間:2017年01月31日 23:35:12   作者:Jesse  
本篇是你必須知道的Javascript系列第二篇,我們主要來看看Javascript中變量作用域的問題,需要的朋友可以參考下

本來是要繼續(xù)由淺入深表達(dá)式系列最后一篇的,但是最近團(tuán)隊突然就忙起來了,從來沒有過的忙!不過喜歡表達(dá)式的朋友請放心,已經(jīng)在寫了:) 在工作當(dāng)中發(fā)現(xiàn)大家對Javascript的一些基本原理普遍存在這里或者那里的一知半解,所以決定先花一些時間整理一下這些基礎(chǔ)知識和大家分享。 后面會附上培訓(xùn)用的PPT。剛開始是打算寫一篇的,但是后來寫著寫著就發(fā)現(xiàn)越來越多,所以決定還是寫一個系列吧。本系列所有內(nèi)容都是涉及Javascript基礎(chǔ)的,沒有時髦的玩意兒,但是我相信這些基礎(chǔ)的東西會有助于你理解那些有趣的東西的。

  本篇是你必須知道的Javascript系列第二篇,我們主要來看看Javascript中變量作用域的問題。主要涉及以下內(nèi)容 :

參數(shù)傳遞的問題
什么是作用域和作用域鏈
塊級作用域
延長作用域鏈
參數(shù)傳遞的問題

  在Javascript中所有的參數(shù)傳遞都是按值傳遞的。也就是說把函數(shù)外部的值復(fù)制給函數(shù)內(nèi)部的參數(shù),就和把值從一個變量復(fù)制到另一個變量一樣?;绢愋椭档膫鬟f如同基本類型變量的復(fù)制一樣,而引用類型值的傳遞,就如同引用類型變量的復(fù)制一樣。

  —— 《Javascript 高級程序設(shè)計》 第三版

function addTen(num) {
 num += 10;
 return num;
}

var count = 20;
var result = addTen(count);
alert(count) // 20
alert(result) // 30

我想關(guān)于值類型的傳遞應(yīng)該很簡單,所以我們就不多說了,重點來看看引用類型的值傳遞。

function setName(person)
{
 person.name = "Jesse";
}

var person = new Object();
setName(person);
alert(person.name); //Jesse

這個函數(shù)把我們外部對象的值也一起改變了,這一點和C#也是一樣的。因為函數(shù)里面的person所指向的地址和外部person所指向的地址是一樣的。下面的行為也是和C#一樣的,即如果在函數(shù)內(nèi)容把參數(shù)指向另外一個對象,不會對外部對象產(chǎn)生影響 。

function setName(person)
{
 person.name="Jesse"
 person = new Object();
 person.name = "Another Jesse";
}

var person = new Object();
setName(person);
alert(person.name); //Jesse

關(guān)于引用類型的拷貝,給初學(xué)者一張圖解。

  1. 在堆中分配一塊空間給person對象,并在棧中保存person在堆中的址址引用
  2. 復(fù)制堆中person的地址引用給person2(同樣是在棧中)
  3. new Person()再次在堆中分配一塊空間給person2對象,然后將棧中person2指向這個新的地址。
  4. 以后對person2的更改不會對person產(chǎn)生影響 

什么是作用域和作用域鏈

  我們知道在JavaScript中有局部變量和全局變量,某個函數(shù)里面的局部變量不能在另一個函數(shù)中被訪問(暫且避開閉包不談)。這就是作用域起的作用,因為變量只在它所在的那個函數(shù)里面起作用。

  每一個函數(shù)都有自己的執(zhí)行環(huán)境,而每一個執(zhí)行環(huán)境都有一個與之相關(guān)聯(lián)的變量對象, 這個環(huán)境中所有變量和函數(shù)就保存在這個變量中。除了函數(shù)有自己的執(zhí)行環(huán)境以外,我們還有一個最大的全局執(zhí)行環(huán)境,而我們所熟知的window就是這個全局執(zhí)行環(huán)境的變量對象,因為所有的全局變量和函數(shù)都是作為window的屬性和方法創(chuàng)建的。每個環(huán)境中的所有代碼執(zhí)行完后,該環(huán)境被隨之銷毀,保存在其中的所有變量和函數(shù)也隨之銷毀。對于全局執(zhí)行環(huán)境來說,關(guān)閉瀏覽器或者退出頁面,那么這個全局的執(zhí)行環(huán)境也就被銷毀了。

  但是,我在這個函數(shù)里面是不是只能訪問這個函數(shù)里面的變量呢?也許大家都知道,還有全局變量,全局變量可以被任意函數(shù)(Javascript沒有像public, private, protected 這樣的關(guān)鍵字),或者任意引入到頁面的js訪問到。這個就是我們常說的作用域鏈。作用域鏈的作用就是保證對執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)進(jìn)行有序訪問。為什么說有序訪問呢? 來看一看下面這段代碼:

var color = "blue";

function alertColor()
{
 var color = "red";
 alert(color);
}

alertColor(); // red
alert(color); // blue

大家知道如果局部變量和全局變量同名的話,全局變量會被覆蓋,但是也不是真正的覆蓋,只是在當(dāng)前這個函數(shù)里面被覆蓋而已,我們在外部依舊可以正常使用的。這里就涉及到一個執(zhí)行環(huán)境有序訪問的問題。

  作用域鏈的最前端永遠(yuǎn)是當(dāng)前執(zhí)行代碼所在環(huán)境的變量對象,對于我們的alertColor而言,就是它自己的活動對象。 所有函數(shù)的活動對象都包含一個初始值,那就是我們的arguments。而作用域鏈的下一個對象,來自包含的外部環(huán)境,一直延續(xù)到全局環(huán)境。所有函數(shù)的作用域鏈都可能延續(xù)到全局環(huán)境,這就是為什么全局變量可以在所有函數(shù)中訪問的原因,并不是因為它叫全局變量,所以它就可以在所有函數(shù)中訪問:) 并且,全局執(zhí)行環(huán)境的環(huán)境變量始終是作用域鏈的最后一個對象。

  我們來看個復(fù)雜一點的例子:

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個執(zhí)行環(huán)境,全局環(huán)境、changeColor的局部執(zhí)行環(huán)境和swapColors的局部執(zhí)行環(huán)境。全局環(huán)境中只有一個變量color和一個函數(shù)changeColor()。changeColor中有一個變量anotherColor和一個函數(shù)swapColors(),但是它可以訪問到全局環(huán)境中的color。swapColors中有一個局部變量tempColor,該變量只不管是在changeColor還是全局環(huán)境中都不能被訪問到,然后在swapColors中可以訪問到其它兩個環(huán)境中的所有變量,因為另外兩個環(huán)境都是它的父執(zhí)行環(huán)境。

我們可以發(fā)現(xiàn),作用域鏈?zhǔn)怯蓛?nèi)向外擴(kuò)展的,我們可以通過作用域訪問外部環(huán)境的變量和函數(shù),但是外部環(huán)境中訪問不到內(nèi)部環(huán)境的變量和函數(shù)。我們在swapColors中用到了全局變量color,但是它也不是一下子就找到color的,它有一個由內(nèi)向外的查找過程:

  1. 在當(dāng)前執(zhí)行環(huán)境內(nèi)尋找叫color的局部變量,沒有找到,向上升一級
  2. 在父級執(zhí)行環(huán)境changeColor中去找叫color的變量,也沒有找到,再向上升一級
  3. 在changeColor的父級中找到了color變量,直接拿過來使用。

塊級作用域
  因為有著塊級作用域(以花括號作為起始點)的存在,C#中這樣的代碼是編譯不通過的。

static void Main(string[] args)
{
 for(var i=0;i<=10;i++)
 {
  Console.Write(i);
 }
 Console.Write(i);
}

我們在for循環(huán)以外已經(jīng)訪問不到i了。但是在Javascript情況就完全不一樣了。

for (var i = 0; i <= 10; i++)
{
 //
}
alert(i); // 11

延長作用域鏈
  我們上面說了,在Javascript中總共只有2種執(zhí)行環(huán)境:全局和局部執(zhí)行環(huán)境。但是我們可以用with和try-catch來延長作用域,由于平常使用場景較少,我們就拿with來舉個例子好了。

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

在with的作用下,location這個變量被加到了作用域的最前端,所以所有l(wèi)ocation下的變量和方法都可以在with的這個范圍內(nèi)訪問了。

  以上就是我們要講的作用域的內(nèi)容了,來總結(jié)一下吧:

  • 值類型按值傳遞,引用類型按引用傳遞。傳遞的行業(yè)和用變量拷貝的行業(yè)是一樣的。
  • Javascript中有兩種執(zhí)行環(huán)境:全局和局部(函數(shù))
  • 執(zhí)行環(huán)境內(nèi)有一個變量對象定義了該執(zhí)行環(huán)境下能訪問的變量和函數(shù)
  • 執(zhí)行環(huán)境可以由內(nèi)向外延伸一直延伸到全局的執(zhí)行環(huán)境
  • Javascript沒有塊級作用域

  下一篇我們來看看Javascript中如果面向?qū)ο蟮木幊?,沒有public, protected, private,等關(guān)鍵字的情況下,我們?nèi)绾蝸韺崿F(xiàn)public 和private 的屬性? 又是如何實現(xiàn)static 類型的變量的? 不要走開,元旦假期之后,我們繼續(xù)Javascript基礎(chǔ)回顧之旅。

相關(guān)文章

  • JavaScript在IE和FF下的兼容性問題

    JavaScript在IE和FF下的兼容性問題

    長久以來JavaScript兼容性一直是Web開發(fā)者的一個主要問題。在正式規(guī)范、事實標(biāo)準(zhǔn)以及各種實現(xiàn)之間的存在的差異讓許多開發(fā)者日夜煎熬。為此,主要從以下幾方面差異總結(jié)IE和Firefox的Javascript兼容性:
    2014-05-05
  • Document對象內(nèi)容集合(比較全)

    Document對象內(nèi)容集合(比較全)

    這個是腳本之家從網(wǎng)上收集的比較全的Document對象內(nèi)容集合,Document對象是js編寫中經(jīng)常用到的對象。了解它方便以后的學(xué)習(xí)。
    2010-09-09
  • Ajax responseText解析json數(shù)據(jù)案例詳解

    Ajax responseText解析json數(shù)據(jù)案例詳解

    這篇文章主要介紹了Ajax responseText解析json數(shù)據(jù)案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • javascript教程之不完整的繼承(js原型鏈)

    javascript教程之不完整的繼承(js原型鏈)

    Javascript的繼承和標(biāo)準(zhǔn)的oop繼承有很大的區(qū)別,Javascript的繼承是采用原型鏈的技術(shù),下面使用示例學(xué)習(xí)一下JS的繼承
    2014-01-01
  • javascript獲取元素CSS樣式代碼示例

    javascript獲取元素CSS樣式代碼示例

    如果想用javascript獲取一個元素的樣式信息,首先想到的應(yīng)該是元素的style屬性,下面我們看看javascript如何獲取元素CSS樣式
    2013-11-11
  • JavaSciprt中處理字符串之sup()方法的使用教程

    JavaSciprt中處理字符串之sup()方法的使用教程

    這篇文章主要介紹了JavaSciprt中處理字符串之sup()方法的使用教程,是JS入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-06-06
  • JSON為什么那樣紅為什么要用json(另有洞天)

    JSON為什么那樣紅為什么要用json(另有洞天)

    json是1年內(nèi)迅速紅遍全球的東東;json.org是一種簡潔有效的數(shù)據(jù)載體,是一種用字符串表示復(fù)雜js對象的方式,后端好生成,前端0解釋,接下來詳細(xì)介紹json風(fēng)行的幾點原因
    2012-12-12
  • 辨析JavaScript中的Undefined類型與null類型

    辨析JavaScript中的Undefined類型與null類型

    Undefined與null都是js中的基本數(shù)據(jù)類型,然而正如它們的名字那樣,未初始化和空并不相同,下面我們就來詳細(xì)辨析JavaScript中的Undefined類型與null類型:
    2016-05-05
  • ECMAscript 變量作用域總結(jié)概括

    ECMAscript 變量作用域總結(jié)概括

    這篇文章主要介紹了ECMAscript 變量作用域,通過使用var操作符聲明和未使用var操作符聲明兩種情景做出了解釋,具體操作步驟大家可查看下文的詳細(xì)講解,感興趣的小伙伴們可以參考一下。
    2017-08-08
  • JavaScript排序算法之希爾排序的2個實例

    JavaScript排序算法之希爾排序的2個實例

    希爾排序,也稱遞減增量排序算法,是插入排序的一種高速而穩(wěn)定的改進(jìn)版本。希爾排序是基于插入排序的以下兩點性質(zhì)而提出改進(jìn)方法的
    2014-04-04

最新評論