this的定義
this指的是函數(shù)運(yùn)行時所在的環(huán)境。(不是定義時所在的環(huán)境)
怎么理解這句話呢?看如下例子:
var w = 1;
var wFunction=function(){
console.log(this.w)
}
var wObj = {
w:2,
wFunction:wFunction
}
wFunction()//1
wObj.wFunction()//2
在這個例子中,首先第一個輸出,因為wFunction是運(yùn)行在全局環(huán)境中,所以this指向全局環(huán)境,所以輸出1;第二個輸出,因為wFunction運(yùn)行在wObj環(huán)境中,所以this指向wObj,而wObj的w屬性值為2,所以輸出2;
那么問題來了,為什么第二個說是在wObj環(huán)境中運(yùn)行呢,運(yùn)行環(huán)境是怎么來判別的呢?這得從內(nèi)存的數(shù)據(jù)結(jié)構(gòu)說起。
內(nèi)存的數(shù)據(jù)結(jié)構(gòu)
首先,是考慮到內(nèi)存的數(shù)據(jù)結(jié)構(gòu),才設(shè)計這個this的。那內(nèi)存的數(shù)據(jù)結(jié)構(gòu)是怎樣的呢,先看個例子:
var wObj = {
w:5
}
console.log(wObj.w)//5
這里,javaScript引擎會在內(nèi)存里先生成一個對象{w:5},然后把這個對象的內(nèi)存地址(reference)賦值給wObj變量。
如果通過wObj.w來讀取這個對象的屬性w,則引擎會先從wObj這個變量拿到對象的內(nèi)存地址,然后從該地址讀出這個對象,返回w屬性。
在看下面一個例子:
var wFunction = function(){
...
}
var wObj = {
wFunc:wFunction
}
console.log(wObj.wFunc())
這里,javaScript引擎會先將函數(shù)function(){...}單獨(dú)保存在內(nèi)存中。然后javaScript引擎會在內(nèi)存里生成一個對象{wFunc:wFunction},而wFunction則是函數(shù)的內(nèi)存地址(reference)。然后把這個對象的內(nèi)存地址賦值給wObj變量。
如果通過wObj.wFunc()執(zhí)行函數(shù),則引擎會先從wObj這個變量拿到對象的內(nèi)存地址,然后從該地址讀出這個對象,返回wFunc屬性,而wFunc屬性的值是函數(shù)function(){...}的內(nèi)存地址(reference),因為這個是單獨(dú)的一個值,所以可以在不同環(huán)境(上下文)執(zhí)行。在這里函數(shù)是通過wObj找到的(wObj的屬性wFunc),所以在wObj環(huán)境中執(zhí)行的。
這里解釋了為啥函數(shù)是可以在不同的環(huán)境中執(zhí)行。那么問題來了,這動態(tài)的執(zhí)行環(huán)境,怎么獲取呢?
this設(shè)計機(jī)制
針對獲取執(zhí)行環(huán)境問題,this就這么設(shè)計出來了,它的設(shè)計目的就是在函數(shù)體內(nèi)部,指代函數(shù)當(dāng)前的運(yùn)行環(huán)境。
回到文章開頭例子,并加以深化如下:
var w = 1;
var wFunction=function(){
console.log(this.w)
}
var wObj = {
w:2,
wFunction:wFunction
}
wFunction()//1
wObj.wFunction()//2
let wObjFunc = wObj.wFunction;
wObjFunc()//1
第一個輸出,函數(shù)執(zhí)行時,是通過全局變量wFunction找到函數(shù)引用地址的,它的執(zhí)行環(huán)境則是全局,因此輸出全局w,為1;
第二個輸出,函數(shù)執(zhí)行時,是通過wObj指向的對象里的wFunction屬性找到的函數(shù)引用地址的,因此,它的執(zhí)行環(huán)境則是wObj指向的對象,因此輸出對象的w,為2;
第三個輸出,函數(shù)執(zhí)行時,是通過全局變量wObjFunc找到函數(shù)引用地址的,(因為let wObjFunc = wObj.wFunction;這直接把函數(shù)的引用地址直接賦給了全局變量wObjFunc,所以wObjFunc直接指向函數(shù)本身)它的執(zhí)行環(huán)境則是全局,因此輸出全局w,為1;