let obj={
a: 100,
read(){
return a; //我知道正確的方法是要加this.
},
}
obj.read(); //Uncaught ReferenceError: a is not defined我粗淺的理解是read()函式內找不到a就到外部的代碼塊找,為什么這兒就找不到a了?
uj5u.com熱心網友回復:
obj.read()(100)uj5u.com熱心網友回復:
并不理解你在說什么。。
uj5u.com熱心網友回復:
{}是個物件,a:100是這個物件的屬性,read(){}是這個物件的方法。return a,這里的a對read方法來說是全域變數的a(因為區域沒有宣告過a,屬性的a也不是區域的),但是全域的a沒定義過,所以出錯。而改成this.a,就會限制使用的是物件的a屬性,該屬性存在,所以沒問題。lz可以在let之前追加以下代碼
var a = 200
看看用return a 和 return this.a 的區別,就知道return a的a是指那個作用范圍的a了。
uj5u.com熱心網友回復:
return a 的 a 是變數 又沒定義a 肯定找不到 變數跟屬性又沒關系uj5u.com熱心網友回復:
謝謝。
我知道你說的這里沒有全域變數a,也知道宣告個全域var a就會return 200。就是覺得物件屬性的a不算區域變數有點奇怪,是不是JS底層規定物件里的屬性不算“物件這個作用域里”的變數啊?(明明全域的window.a就可以被全域訪問。)
uj5u.com熱心網友回復:
我理解成一個嵌套。read方法的確找不到區域變數a,那也不應該立即到全域去找啊,難道不是去外一層的作用域找嗎?外一層就是obj物件啊,這里有a啊,就這么選擇性失明了?
uj5u.com熱心網友回復:
你的意思是,物件的屬性,不能算變數?
可是全域window.a這個屬性,算變數吧?
uj5u.com熱心網友回復:
read(){}的作用域在{}里,也就是區域在{}里,找不到就找全域變數但是this.a就限定了read是用屬性的a,即不是區域的,也不是全域的。這就用是this的區別。
uj5u.com熱心網友回復:
屬性不是區域變數(它跟著物件走),read()函式的上一層作用域是main(因為是main函式呼叫read的),所以read找上一層作用域就是找main的a,也就是全域的a。this.a不在函式堆疊里,如果物件在堆里,this.a也在堆里,所以read是找不到它的,只有用了this,read才知道去哪找它。
uj5u.com熱心網友回復:
如果a屬性在read中直接就能訪問的話,那么a屬性就很容易被污染,所以要指明this.a才能訪問到auj5u.com熱心網友回復:
謝謝,基本明白你的意思。
還是想鉆個牛角尖。你說道“屬性不是區域變數”,那全域物件里加個var a=200,即window.a=200,這時候,a可以看作是window物件的屬性吧?那a怎么又同時可以算作window物件的變數呢?
uj5u.com熱心網友回復:
js其實有個模塊的概念,window是內置的模塊,在模塊定義的全域變數會被該模塊的全部代碼可見。該模塊被export出去時,該全域變數會export成為模塊的成員(屬性)。所以,其他代碼能用a,是因為他們都在同一個window模塊(不同模塊必須用模塊名.a來使用),并不是因為它是一個window的屬性,所以它跟物件的屬性不在堆疊里不是一回事uj5u.com熱心網友回復:
在賦值=的運算式中{}是個物件字面量,只是創建個物件,并不會產生作用域。直接訪問a,是在當前作用域鏈中查找a。當前作用域鏈只有read()函式作用域和全域作用域window。
并沒有obj物件的作用域,只是把read()函式內的this指向了obj物件而已。
uj5u.com熱心網友回復:
window物件能成為作用域是因為在前端瀏覽器中系統把window物件與全域作用域Global物件融合了。這是個特例。uj5u.com熱心網友回復:
回帖太多,否則我就給你解釋清楚。轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/254631.html
標籤:JavaScript
