亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Javascript Context和Scope的學(xué)習(xí)總結(jié)01【轉(zhuǎn)自cnblogs的JKhuang】

April / 2866人閱讀

摘要:正文執(zhí)行環(huán)境也稱為環(huán)境是中最為重要的一個概念。執(zhí)行環(huán)境定義了變量或函數(shù)有權(quán)訪問的其他數(shù)據(jù),決定了它們各自的行為。簡而言之,執(zhí)行環(huán)境是基于對象的,而作用域是基于函數(shù)的。

前述

在我們學(xué)習(xí)Javascript過程中,常常會遇到作用域(Scope)和執(zhí)行上下文(Context)等概念。其中,執(zhí)行上下文與this關(guān)鍵字的關(guān)系密切。

有面向?qū)ο缶幊探?jīng)驗的各位,對于this關(guān)鍵字再熟悉不過了,因此我們很容易地把它和面向?qū)ο蟮木幊谭绞铰?lián)系在一起,它指向利用構(gòu)造器新創(chuàng)建出來的對象;在ECMAScript中,也支持this,然而, 正如大家所熟知的,this不僅僅只用來表示創(chuàng)建出來的對象。

在接下來的博文我們講介紹Javascript的作用域和執(zhí)行上下文,以及它們的異同之處。

正文

執(zhí)行環(huán)境(Execution context)也稱為“環(huán)境”是Javascript中最為重要的一個概念。執(zhí)行環(huán)境定義了變量或函數(shù)有權(quán)訪問的其他數(shù)據(jù),決定了它們各自的行為。每個執(zhí)行環(huán)境都有一個與之關(guān)聯(lián)的變量對象,環(huán)境中定義的所有變量和函數(shù)都保存在這個對象中。

看到了執(zhí)行環(huán)境的定義有點頭昏了,簡而言之“每個執(zhí)行環(huán)境都有一個與之關(guān)聯(lián)的變量對象”;這里我們有一個疑問就是這個變量對象是怎樣定義的呢?

接下來,讓我們看一下變量對象的定義,具體實現(xiàn)如下:

/**
 * Execution context skeleton.
 */
activeExecutionContext = {
    // variable object.
    VO: {...},
    this: thisValue
};

通過上面的偽代碼我們知道對象字面量activeExecutionContext,它包含一個變量對象VO和this屬性。

這說明了this與上下文的可執(zhí)行代碼類型有關(guān),其值在進入上下文階段就確定了,并且在執(zhí)行代碼階段是不能改變的(關(guān)于this使用可以閱讀《Javascript this 的一些學(xué)習(xí)總結(jié)》)。

作用域(Scope)控制著變量和參數(shù)的可見性及生命周期。

簡而言之,執(zhí)行環(huán)境是基于對象的,而作用域是基于函數(shù)的。

作用域

我們將通過一個例子介紹作用域的使用,首先,我們定義了一個函數(shù)FooA()和FooB,示例代碼如下:

/**
 * Defines a function.
 */
var FooA = function(){
    var a = 1;
    var FooB = function(){
        var b = 2;
        console.log(a, b); // outputs: 1, 2
    }
    console.log(a, b); // Error! b is not defined
}
FooA();

在示例中,第二個log輸出變量為未定義,這是由于在Javascript中定義在函數(shù)里面的參數(shù)和變量在函數(shù)外部是不可見的,而在一個函數(shù)內(nèi)部任何位置定義的參數(shù)和變量,在該函數(shù)內(nèi)部任何地方都是可見的。

執(zhí)行環(huán)境

首先,我們定義了對象字面量o,它包含一個屬性x和方法m(),示例代碼如下:

/**
 * Defines a literal object.
 * @type {Object}
 */
var o = {
    x:23,
    m: function(){
        var x = 1;
        console.log(x, this.x); // outputs 1, 23
    }
}
o.m();

示例中的兩個變量和屬性x都能被訪問,但它們被訪問的方式是截然不同,在log中訪問第一個x是通過作用域方式訪問了本地變量x,而this.x是通過執(zhí)行上下文方式訪問對象o的屬性x,因此輸出值也不盡相同。

上下文問題

接下來,我們修改一下前面的例子,在方法m()中添加一個函數(shù)f(),示例代碼如下:

/**
 * Defines a literal object.
 * @type {Object}
 */
var o = {
    x:23,
    m: function(){
        var x = 1;
        var f = function(){
            console.log(x, this.x); // outputs 1, undefined
        }
        f();
    }
}
o.m();

上面,我們通過調(diào)用方法m()來輸出x的值,由于方法m()的具體實現(xiàn)是通過調(diào)用函數(shù)f()來實現(xiàn)。

當(dāng)我們調(diào)用對象o的方法m()時,發(fā)現(xiàn)this.x是未定義的。

這究竟是什么原因呢?回憶前面的例子,由于方法m()獲取了對象o的上下文,所以this是指向?qū)ο髈的,難道是函數(shù)f()沒有獲取對象o的上下文,因此它不清楚this指向哪個對象?

首先讓我們回顧一下函數(shù)和方法以及屬性和變量的區(qū)別:方法和對象關(guān)聯(lián),如:object.myMethod = function() {},而函數(shù)非對象關(guān)聯(lián):var myFunc = function {};同樣屬性也是對象關(guān)系的,如:object.myProperty = 23,而變量:var myProperty = 23。

因為我們提到上下文是基于對象的,所以函數(shù)f()不能獲取對象o的執(zhí)行上下文。

我們是否可以讓函數(shù)f()獲取對象o的執(zhí)行上下文呢?我們仔細(xì)地想一下,既然函數(shù)f()不清楚this指向的對象,那么可以直接調(diào)用對象的屬性就OK了。

/**
 * Fixs broken context issue.
 * @type {Object}
 */
var o = {
    x:23,
    m: function(){
        var x = 1;
        var f = function(){
            console.log(x, o.x); // outputs 1, 23
        }
        f();
    }
}
o.m();

我們在函數(shù)f()中直接調(diào)用對象o的屬性x,這樣函數(shù)f()就無需獲取執(zhí)行上下文直接調(diào)用對象的屬性了。

現(xiàn)在,我們又遇到一個新的問題了,如果對象不是o而是p,那么我們就需要修改函數(shù)f()中的對象了,更嚴(yán)重的情況就是我們沒有辦法確定具體是哪個對象,示例代碼如下:

/**
 * Defines a literal object.
 * @constructor
 */
var C = function(){}
C.prototype = {
    x:23,
    m: function(){
        var x = 1;
        var f = function(){
            console.log(x, this.x); // outputs 1, undefined
        }
        f();
    }
}
var instance1 = new C();
instance1.m();

上下文實例問題

上面,我們定義了函數(shù)C和它的原型對象,而且我們可以通過new方式創(chuàng)建C對象實例instance1,按照前面的方法解決Broken Context問題,具體實現(xiàn)如下:

/**
 * Defines a literal object.
 * @constructor
 */
var C = function(){}
C.prototype = {
    x:23,
    m: function(){
        var x = 1;
        var f = function(){
            console.log(x, instance1.x); // outputs 1, undefined
        }
        f();
    }
}
var instance1 = new C();
instance1.m();

如果我們在創(chuàng)建一個C的對象實例instance2,那么我們就不能指定函數(shù)f()中的對象了。

其實,this是對象實例的抽象,當(dāng)實例有多個甚至成千上百個的時候,我們需要通過this引用這些對象實例。

因此,指定對象方法不能有效解決Broken Context問題,我們還是需要使用this來引用對象,前面我們講到由于函數(shù)f()沒有獲取對象o的執(zhí)行上下文,因此它不清楚this指向哪個對象,所以輸出this.x未定義,那么我們是否可以讓函數(shù)f()獲取對象的執(zhí)行上下文。

跨作用域的上下文

我們想想既然方法是基于對象的,而且可以獲取對象的執(zhí)行上下文,那么我們直接把f()定義為方法好了。

現(xiàn)在,我們在C對象原型中定義方法f(),示例代碼如下:

/**
 * Defines a literal object.
 * @constructor
 */
var C = function(){}

C.prototype = {
    x:10,
    m: function(){
        var x = 1;
        this.f();
    },
    f: function(){
        console.log(x, this.x); // Reference ERROR!!
    }
}
var instance1 = new C();
instance1.m();

好啦,我們在C對象原型中定義方法f(),那么方法f()就可以獲取對象的執(zhí)行上下文。

現(xiàn)在,我們在Firefox運行以上代碼,結(jié)果輸出Reference ERROR,這究竟是什么原因呢?我們想了一下問題出于變量x中,由于方法f()不能獲取方法m()的作用域,所以變量x不在方法f()中。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/88099.html

相關(guān)文章

  • Javascript ContextScope學(xué)習(xí)總結(jié)02【轉(zhuǎn)自cnblogsJKhuang

    摘要:總結(jié)本博文通過介紹執(zhí)行上下文和作用域的異同的使用以及變量對象,讓我們加深對語言特性的理解。首先,我們介紹了執(zhí)行上下文和的的關(guān)系,并且執(zhí)行上下文是具有對象的然后,介紹了作用域使變量在作用域范圍內(nèi)可見,并且作用域是基于函數(shù)的。 接上一篇Javascript Context和Scope的學(xué)習(xí)總結(jié)01【轉(zhuǎn)自cnblogs的JKhuang】(可能是segmentfault對單篇文章發(fā)布字?jǐn)?shù)有限制...

    Aldous 評論0 收藏0
  • Javascript this 一些學(xué)習(xí)總結(jié)01轉(zhuǎn)自cnblogsJKhuang

    摘要:函數(shù)上下文中的值是函數(shù)調(diào)用者提供并且由當(dāng)前調(diào)用表達式的形式而定的。然而,由于對于來說沒有任何意義,因此會隱式轉(zhuǎn)換為全局對象。這里注意到四個表達式中,只有第一個表達式是指向?qū)ο蟮模渌齻€表達式則執(zhí)行。 摘要 相信有C++、C#或Java等編程經(jīng)驗的各位,對于this關(guān)鍵字再熟悉不過了。由于Javascript是一種面向?qū)ο蟮木幊陶Z言,它和C++、C#或Java一樣都包含this關(guān)鍵字...

    Thanatos 評論0 收藏0
  • Javascript this 一些學(xué)習(xí)總結(jié)02【轉(zhuǎn)自cnblogsJKhuang

    摘要:發(fā)生這種情況的條件是當(dāng)引用類型值的對象恰好為活躍對象。總結(jié)本文介紹中的使用,更重要的是幫助我們能更好地理解值在全局函數(shù)構(gòu)造函數(shù)以及一些特例的情況中值的變化。然而,由于對于來說沒有任何意義,因此會隱式轉(zhuǎn)換為全局對象。 接上一篇Javascript this 的一些學(xué)習(xí)總結(jié)02【轉(zhuǎn)自cnblogs的JKhuang】 引用類型以及this的null值 對于前面提及的情形,還有例外的情況,當(dāng)調(diào)...

    suemi 評論0 收藏0
  • javascript作用域,作用域鏈,[[scope]]屬性

    摘要:正式由于作用域鏈的這種關(guān)系,我們就不難理解,為什么和不能通過作用域鏈向上搜索,因為對和的搜索在當(dāng)前執(zhí)行函數(shù)的活動對象就停止了。 對于Javascript程序員來說,閉包總會讓你覺得既熟悉又陌生,然而它對于開發(fā)人員來說卻非常重要,javascript里的許多設(shè)計模式中都用到了閉包,此處以函數(shù)作用域為例。 //示例代碼 var a=1; function foo(){ ...

    pkhope 評論0 收藏0
  • JavaScript閉包

    摘要:此時的作用域鏈包含了兩個對象的活動對象和對象。閉包的應(yīng)用場景保護函數(shù)內(nèi)的變量安全。依然如前例,由于閉包,函數(shù)中的一直存在于內(nèi)存中,因此每次執(zhí)行,都會給自加。 引子 JS的閉包一直是很多人不理解,也是在使用過程中經(jīng)常出現(xiàn)問題的地方。每次看文章都會有所了解閉包,但是,用起來還是不對,而且錯誤百出,其關(guān)鍵問題還是出在對其不理解,不了解。此文章會不定期更新以及完善,希望在我學(xué)習(xí)的時候,讓大家也...

    Tony 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<