成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript中this終極理解(2)

liujs / 1998人閱讀

摘要:找到函數(shù)的調(diào)用位置最重要的是要分析調(diào)用棧就是為了到達(dá)當(dāng)前執(zhí)行位置所調(diào)用的所有函數(shù)。顯示綁定我們可以使用函數(shù)的和方法,通過(guò)這兩個(gè)方法可以在某個(gè)對(duì)象上強(qiáng)制調(diào)用函數(shù)。

在上一篇我們了解過(guò)每個(gè)函數(shù)的this是在調(diào)用的時(shí)候綁定的,完全卻決于函數(shù)的調(diào)用位置(也就是函數(shù)的調(diào)用方法)。

1. 調(diào)用位置

在理解this的綁定過(guò)程之前,首先要理解調(diào)用位置:調(diào)用位置就是函數(shù)在代碼中被調(diào)用的位置,而不是聲明的位置。

找到函數(shù)的調(diào)用位置最重要的是要分析調(diào)用棧(就是為了到達(dá)當(dāng)前執(zhí)行位置所調(diào)用的所有函數(shù))。我們關(guān)心的調(diào)用位置就在當(dāng)前正在執(zhí)行的函數(shù)的前一個(gè)調(diào)用中。

function baz() {
    //當(dāng)前調(diào)用棧是:baz
    //因此,當(dāng)前調(diào)用位置是全局作用域
    console.log("baz");
    bar(); //<--bar的調(diào)用位置
}

function bar() {
    //當(dāng)前調(diào)用棧是baz->bar
    //因此,當(dāng)前調(diào)用位置在baz中
    console.log("bar")
    foo(); 
}

function foo() {
    //當(dāng)前調(diào)用棧是baz->bar->foo
    //因此,當(dāng)前調(diào)用位置在bar中
    console.log("foo")
}
baz() //<---baz得調(diào)用位置
2. 綁定規(guī)則

那么調(diào)用位置如何決定this得綁定對(duì)象呢。首先,我們要找到調(diào)用位置,然后按照下面四條規(guī)則進(jìn)行應(yīng)用。首先我們先了解下這幾條規(guī)則:

(1)默認(rèn)綁定

首先介紹最常用得函數(shù)調(diào)用類型:獨(dú)立函數(shù)調(diào)用。可以將這條規(guī)則看作是無(wú)法應(yīng)用其他規(guī)則得默認(rèn)規(guī)則。

function foo() {
    console.log(this.a)
}
var a = 2;
foo(); //2

上面得代碼中,在全局環(huán)境中聲明了一個(gè)變量a,那么a就是全局對(duì)象得一個(gè)同名屬性。當(dāng)調(diào)用foo()時(shí),this.a被解析成了全局變量a。因?yàn)楹瘮?shù)調(diào)用得時(shí)候應(yīng)用了this得默認(rèn)綁定,因此this指向全局對(duì)象。
在代碼中,foo()是直接使用不帶任何修飾的函數(shù)引用進(jìn)行調(diào)用,因此只能使用默認(rèn)綁定。

如果使用嚴(yán)格模式,那么全局對(duì)象將無(wú)法使用默認(rèn)綁定,因此this會(huì)綁定到undefined。

(2)隱式綁定

另一條需要考慮的規(guī)則是調(diào)用位置是否有上下文對(duì)象,或則說(shuō)是否被某個(gè)對(duì)象擁有或者包含。

function foo() {
    console.log(this.a)
}
var obj = {
    a: 2,
    foo: foo
}
obj.foo(); //2

首先需要注意的是foo()的聲明方式,以及之后是如何被當(dāng)作引用屬性添加到obj中的。但是無(wú)論是直接在obj定義還是先定義再添加為引用屬性,這個(gè)函數(shù)嚴(yán)格來(lái)說(shuō)都不屬于obj對(duì)象。

調(diào)用位置會(huì)使用obj上下文來(lái)引用函數(shù),因此你可以說(shuō)函數(shù)被調(diào)用時(shí),obj對(duì)象"擁有"或者"包含"它。

當(dāng)foo()調(diào)用時(shí),它的落腳點(diǎn)確實(shí)指向obj對(duì)象。當(dāng)函數(shù)引用有上下文對(duì)象時(shí),隱式綁定規(guī)則會(huì)把函數(shù)調(diào)用中的this綁定到這個(gè)上下文對(duì)象。因?yàn)檎{(diào)用foo()時(shí)this被綁定到obj,因此this.a和obj.a時(shí)一樣的。

對(duì)象屬性引用鏈中只有最頂層或者最后一層會(huì)影響調(diào)用位置。

function foo() {
    console.log(this.a)
}
var obj2 = {
    a: 42,
    foo: foo
}
var obj1 = {
    a: 2,
    obj2: obj2
}
obj1.obj2.foo() //42

隱式丟失

this綁定一個(gè)常見的問(wèn)題就是被隱式綁定的函數(shù)會(huì)丟失綁定對(duì)象,也就是說(shuō)它會(huì)應(yīng)用默認(rèn)綁定,從而把this綁定到全局對(duì)象或者undefined上,這要取決于是否式嚴(yán)格模式。

function foo() {
    console.log(this.a)
}
var obj = {
    a:2,
    foo: foo
}
var bar = obj.foo; //函數(shù)別名
var a = "oops, globas"; //a式全局對(duì)象的屬性
bar(); //"oops, globas"

雖然bar是obj.foo的引用,但實(shí)際上,它引用的是foo函數(shù)本身,因此此時(shí)的bar()其實(shí)是一個(gè)不帶任何修飾的函數(shù)調(diào)用,因此應(yīng)用默認(rèn)綁定。

再看下面一組代碼:

function foo() {
    console.log(this.a)
}
function doFoo(fn) {
    fn();
}

var obj = {
    a:2,
    foo:foo
}
var a = "oops,global"
doFoo(obj.foo); //"oops, global"

參數(shù)傳遞其實(shí)就是一種隱式賦值,因此我們傳入函數(shù)時(shí)也會(huì)被隱式賦值,所以結(jié)果和之前一樣。

(3)顯示綁定

我們可以使用函數(shù)的call()apply()方法,通過(guò)這兩個(gè)方法可以在某個(gè)對(duì)象上強(qiáng)制調(diào)用函數(shù)。
這兩個(gè)方法的作用都是一樣的,第一個(gè)參數(shù)是一個(gè)對(duì)象,它們會(huì)把這個(gè)對(duì)象綁定到this,接著在調(diào)用函數(shù)時(shí)指定這個(gè)this。因?yàn)榭梢灾苯又付╰his的綁定對(duì)象,因此叫做顯示綁定

function foo() {
    console.log(this.a)
}
var obj = {
    a: 2
}
foo.call(obj); //2

通過(guò)foo.call(..),我們可以在調(diào)用foo時(shí)強(qiáng)制把它的this綁定到obj上。

如果你傳入了一個(gè)原始值(字符串類型,布爾類型等)來(lái)當(dāng)作this的綁定對(duì)象,這個(gè)原始值會(huì)被轉(zhuǎn)換成對(duì)象形式,也就是(new String(..)),這通常被稱為"裝箱"。

function foo() {
    console.log(this.a)
}
var obj = {
    a:2
}
var bar = function() {
    foo.call(obj)
}
bar();//2
setTimeout(bar, 10); //2
bar.call(window); //2

如上,我們不管怎么調(diào)用bar,它總會(huì)手動(dòng)在obj上調(diào)用foo,這種綁定時(shí)一種顯示的強(qiáng)制綁定,因此我們稱為為硬綁定。

硬綁定的典型應(yīng)用場(chǎng)景就是創(chuàng)建一個(gè)包裹函數(shù),傳入所有的參數(shù)并返回接收到的所有值:

function foo(something) {
    console.log(this.a, something)
    return this.a + something
}

//簡(jiǎn)單的輔助綁定函數(shù)
function bind(fn, obj) {
    return function() {
        return fn.apply(obj, arguments)
    }
}

var obj = {
    a: 2
};
var bar = bind(foo, obj)

var b = bar(3) //2, 3
console.log(b) //5

bind(...)會(huì)返回一個(gè)硬編碼的新函數(shù),它會(huì)把參數(shù)設(shè)置為this的上下文并調(diào)用原始函數(shù)。

(4) new綁定

在JavaScript中,構(gòu)造函數(shù)只是一些使用new操作符時(shí)被調(diào)用的函數(shù)。他們并不會(huì)屬于某個(gè)類,也不會(huì)實(shí)例化一個(gè)類。實(shí)際上他們甚至都不能說(shuō)時(shí)一種特殊的函數(shù)類型。只是被new操作符調(diào)用的普通函數(shù)。

使用new來(lái)調(diào)用函數(shù)時(shí)會(huì)執(zhí)行以下操作:

1. 創(chuàng)建一個(gè)全新的對(duì)象
2. 這個(gè)新對(duì)象會(huì)被執(zhí)行[[原型]]連接
3. 這個(gè)新對(duì)象會(huì)綁定到函數(shù)調(diào)用的this
4. 如果函數(shù)沒有返回其他對(duì)象,那么new表達(dá)式中的函數(shù)調(diào)用會(huì)自動(dòng)返回這個(gè)新對(duì)象。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/90022.html

相關(guān)文章

  • JavaScriptthis終極理解(1)

    摘要:關(guān)鍵字是中一個(gè)復(fù)雜的機(jī)制,它被自動(dòng)定義在所有的函數(shù)作用域中。指向它自身匿名函數(shù)無(wú)法指向自身第一個(gè)函數(shù)被稱為具名函數(shù),在它內(nèi)部可以使用來(lái)引用自身。的綁定和函數(shù)聲明的位置沒有任何關(guān)系,取決于函數(shù)的調(diào)用方式。這是理解的前提。 this關(guān)鍵字是JavaScript中一個(gè)復(fù)雜的機(jī)制,它被自動(dòng)定義在所有的函數(shù)作用域中。 1. 為什么要用this function identify() { ...

    YacaToy 評(píng)論0 收藏0
  • 筆試題之Event Loop終極

    摘要:下面開始分析開頭的代碼第一輪事件循環(huán)流程整體作為第一個(gè)宏任務(wù)進(jìn)入主線程,遇到,輸出遇到函數(shù)聲明,聲明暫時(shí)不用管遇到,其回調(diào)函數(shù)被分發(fā)到微任務(wù)中。我們記為遇到,其回調(diào)函數(shù)被分發(fā)到宏任務(wù)中。 先上一道常見的筆試題 console.log(1); async function async1() { console.log(2); await async2(); con...

    niceforbear 評(píng)論0 收藏0
  • 面試題之Event Loop終極

    摘要:下面開始分析開頭的代碼第一輪事件循環(huán)流程整體作為第一個(gè)宏任務(wù)進(jìn)入主線程,遇到,輸出遇到函數(shù)聲明,聲明暫時(shí)不用管遇到,其回調(diào)函數(shù)被分發(fā)到微任務(wù)中。我們記為遇到,其回調(diào)函數(shù)被分發(fā)到宏任務(wù)中。 先上一道常見的筆試題 console.log(1); async function async1() { console.log(2); await async2(); con...

    233jl 評(píng)論0 收藏0
  • jsthis的“終極三問(wèn)”

    摘要:是什么本質(zhì)是一個(gè)綁定,在函數(shù)被調(diào)用時(shí)建立。它的指向是完全由函數(shù)被調(diào)用的調(diào)用點(diǎn)來(lái)決定的。因?yàn)楹瘮?shù)的調(diào)用點(diǎn)在全局作用域,所以指向全局變量這里就是函數(shù)的調(diào)用點(diǎn)存在的意義在函數(shù)體內(nèi)部指代函數(shù)當(dāng)前的運(yùn)行環(huán)境。從而實(shí)現(xiàn)干凈的設(shè)計(jì)和更容易的復(fù)用。 this是什么? this 本質(zhì)是一個(gè)綁定, 在函數(shù)被調(diào)用時(shí)建立。它的指向是完全由函數(shù)被調(diào)用的調(diào)用點(diǎn)來(lái)決定的。 function baz() { ...

    silvertheo 評(píng)論0 收藏0
  • 終極蛇皮上帝視角之微信小程序之告別 setData

    摘要:而小程序官方的是在中調(diào)用方法來(lái)改變數(shù)據(jù),從而改變界面。為了寫測(cè)試讓咱們來(lái)重構(gòu)一把,利用學(xué)習(xí)過(guò)的函數(shù)式編程中的高階函數(shù)把依賴注入。也就是說(shuō)當(dāng)中的某個(gè)數(shù)據(jù)更新的時(shí)候,我們并不知道它會(huì)影響哪個(gè)中的屬性,特別的還有依賴于的情況。 眾所周知 Vue 是借助 ES5 的 Object.defineProperty 方法設(shè)置 getter、setter 達(dá)到數(shù)據(jù)驅(qū)動(dòng)界面,當(dāng)然其中還有模板編譯等等其他...

    wuyumin 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<