例如,我們定義一個函數(shù) getUrl
和一個對象 pseudoWindow
。
function getUrl() {
console.log(this.document.URL);
}
var pseudoWindow = {
document: {
URL: "I'm fake URL"
},
getUrl1: getUrl,
getUrl2: function (callback) {
callback();
this.func = callback;
this.func();
}
}
執(zhí)行 getUrl()
,打印出當(dāng)前頁面的 URL。
執(zhí)行 pseudoWindow.getUrl1()
,打印出 I'm fake URL
。
執(zhí)行 pseudoWindow.getUrl2(getUrl)
,先打印出當(dāng)前頁面 URL,后打印 I'm fake URL
。
下面讓我們用最簡單粗暴的語言來解釋以上代碼。
概念 什么是 this?this 就是函數(shù)調(diào)用使用的上下文。
什么是上下文?上下文是在句號標(biāo)記法中,句號前面的那個東西。
例如 pseudoWindow.getUrl1
,pseudoWindow
是 pseudoWindow.getUrl1()
的上下文。
當(dāng)一個變量沒有綁定到任何上下文時(或者說綁定到頂級作用域時,例如瀏覽器中的 window),它就是自由變量。
什么是變量與對象?變量就是代碼中你所用的標(biāo)識符,一個標(biāo)識符就是一個變量,多個變量可能指向同一個對象。例如:
pseudoWindow.getUrl1 === getUrl // 得到 true
變量所處的上下文就是對象的作用域。
代碼分解 調(diào)用 getUrl()首先 getUrl
函數(shù)是定義在全局環(huán)境中,它是一個自由變量,在瀏覽器中(以下描述均為瀏覽器環(huán)境)它的上下文就是 window
,所以 window.getUrl()
和 getUrl()
是等價的。因此 this
指向 window
對象,打印出當(dāng)前 URL。
首先 pseudoWindow
是一個對象,它可以充當(dāng)上下文角色。我們給它定義了一個屬性 getUrl1
,你可以將屬性視為被綁定到某個上下文的變量,變量 getUrl1
本身又指向了變量 getUrl
所指向的對象,所以 pseudoWindow.getUrl1 === getUrl
才會為 true
。
當(dāng)我們調(diào)用 pseudoWindow.getUrl1()
時,它的意思是執(zhí)行 getUrl()
這段代碼,執(zhí)行代碼所需的參數(shù)為空,上下文為 pseudoWindow
。
所以函數(shù)中的 this
指向了 pseudoWindow
,而 pseudoWindow
對象恰好又有 document
屬性,該屬性恰好又有 URL
屬性,因此打印出 I'm fake URL
。
同理我們又定義了一個變量 getUrl2
,并綁定到 pseudoWindow
對象身上,使之成為后者的一個屬性。而這個屬性本身又指向一個匿名函數(shù),我們姑且稱之為 A,該函數(shù)對象接受另一個函數(shù)對象作為回調(diào)函數(shù)。
因此執(zhí)行 pseudoWindow.getUrl2(getUrl)
時,意思是執(zhí)行代碼 A,執(zhí)行代碼所需的參數(shù)為 getUrl
這段代碼,上下文為 pseudoWindow
。
因此函數(shù) A 中的 this
指向了 pseudoWindow
。
當(dāng)程序執(zhí)行到函數(shù) A 內(nèi)部的 callback()
時,因?yàn)樽兞?callback
沒有綁定到任何上下文,因此它相當(dāng)于一個自由變量,它的上下文就指向了 window
對象,因此首先打印出當(dāng)前頁面的 URL。
接下來 this.func = callback
意味著三件事:
func
。
通過 =
操作符,我們將該變量指向了 callback
所指向的函數(shù)對象。
通過 .
操作符,我們將該變量綁定到了 this
對象上,使之成為后者的一個屬性,而本例中 this
指向的就是 pseudoWindow
對象。于是當(dāng)程序執(zhí)行到 this.func()
時,它的意思是執(zhí)行 callback
這段代碼,執(zhí)行代碼所需的參數(shù)為空,上下文為 pseudoWindow
。于是打印出了 I'm fake URL
。
這段代碼帶來的一個副作用是我們隱式地為 pseudoWindow
對象添加了一個新的屬性 func
,如果我們想要通過回調(diào)的方式打印出 pseudoWindow
的 document.URL
屬性,又不想對 pseudoWindow
對象造成任何影響,那么我們可以使用函數(shù)的 apply
方法。所有函數(shù)都有 apply
方法,它會將它接收的第一個參數(shù)設(shè)置為函數(shù)的上下文。
例如本例中我們可以改寫代碼成這樣子:
var pseudoWindow = {
document: {
URL: "I'm fake URL"
},
getUrl1: getUrl,
getUrl2: function (callback) {
callback();
callback.apply(this);
}
}
總結(jié)嚴(yán)格地說,你應(yīng)該先檢查 callback 參數(shù)類型是否是函數(shù)對象。
Javascript 支持將函數(shù)作為參數(shù)傳遞,回調(diào)函數(shù)變量指向的函數(shù)對象都未與任何上下文綁定,所有未與明確上下文綁定的變量都是自由變量,瀏覽器器中所有自由變量的上下文都是 window 對象。
網(wǎng)站欄目:理解JS回調(diào)函數(shù)中的this-創(chuàng)新互聯(lián)
本文地址:http://aaarwkj.com/article4/gogoe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、App設(shè)計、移動網(wǎng)站建設(shè)、自適應(yīng)網(wǎng)站、網(wǎng)站收錄、網(wǎng)站排名
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容