摘要:一個(gè)表示編譯器檢測(cè)到一個(gè)無效的引用值。在實(shí)際情況中,往往是在獲取一個(gè)未被賦值的引用時(shí)被拋出。任何一個(gè)函數(shù)上下文都有一個(gè)被稱為活動(dòng)對(duì)象的變量對(duì)象。沒有找到的話,就會(huì)認(rèn)為引用名沒有基礎(chǔ)值并拋出的錯(cuò)誤。下沒有下的屬性僅存在于被啟動(dòng)的情況下。
和其他語言相比,javascript中的對(duì)于undefined的理解還是有點(diǎn)讓人困惑的。特別是試著理解ReferenceErrors錯(cuò)誤("x is not defined")以及在編碼過程中如何去避免這些錯(cuò)誤總讓人感到比較困惑。
這篇文章是我整理的關(guān)于這個(gè)知識(shí)點(diǎn)的內(nèi)容。如果你對(duì)于javascript中的變量以及屬性還不是很熟悉的話,你可以看看我之前寫的[文章]()
undefined是什么?在Javascript中,存在著Undefined(基本類型),undefined(值),以及defedined(變量)。
Undefined(基本類型)是js內(nèi)置的基本類型之一(String, Number, Boolean, Null, Object)
undefined(值)是一個(gè)原始值,是未定義類型的基礎(chǔ)值。任何未被賦值的屬性值都可以假設(shè)為undefined。無返回值或者返回值為空的函數(shù)最后執(zhí)行得到的值都未undefined。未設(shè)定的函數(shù)參數(shù)值也為undefined.
var a; typeof a; // undefined window.b; typeof window.b; // undefined var c = (function() {})(); typeof c; // undefined var d = (function(e) {return e})(); typeof d; // undefined
undefined(變量)是初始值為undefined的全局屬性,既然它是個(gè)全局屬性,那么我們也可以通過變量來獲取它。例如我在這篇文章里面像這樣將它作為一個(gè)變量來獲取它。
typeof undefined; // undefined var f = 2; f = undefined; //重新將變量f賦值為變量undefined typeof f; // undefined
在ECMA3當(dāng)中,它的值可以重新被賦值:
undefined = "washing machine"; typeof undefined; // string f = undefined; typeof f; // string f; // "washing machine"
不用說,將undefined重新賦值是一個(gè)比較糟糕的用法。事實(shí)上再ECMA5當(dāng)中這種做法也是不被允許的。
And then there"s null?大致上我們了解這兩者之間的區(qū)別,但是還是需要重新復(fù)述一遍:undefined和null相比,undefined是一個(gè)原始值,它表示一個(gè)缺省值。undefined和null之間唯一相似的地方就是它們都能被通過類型轉(zhuǎn)換成false。
So what"s a RefernceError?一個(gè)ReferenceError表示編譯器檢測(cè)到一個(gè)無效的引用值。
在實(shí)際情況中,ReferenceError往往是在Javascript獲取一個(gè)未被賦值的引用時(shí)被拋出。
注意下在不同瀏覽器中,ReferenceError現(xiàn)在的不同的語法錯(cuò)誤提示信息。正如我們看到的,在不同瀏覽器中,錯(cuò)誤信息并非特別的清楚明了。
alert(foo); //FF/Chrome: foo is not defined //IE: foo is undefined //Safari: can"t find variable fooStill not clear ..."unresolvable reference"?
在ECMA標(biāo)準(zhǔn)中,一個(gè)引用值包含一個(gè)引用名稱及一個(gè)基本值。
如果這個(gè)引用是一個(gè)屬性,那么基礎(chǔ)值及這個(gè)引用分別位于點(diǎn)號(hào)的兩側(cè):
window.foo; // base value = window, reference name = foo; a.b; //base value = a, reference name = b; myObj["create"]; //base value = myObj, reference name = create; //Safari, Chrome, IE8+ only Object.defineProperty(window, "foo", {value: "hello"}); //base value = window. reference name = foo;
對(duì)于引用變量來說,基礎(chǔ)值是當(dāng)前執(zhí)行上下文的變量對(duì)象。全局上線文的變量對(duì)象就是全局對(duì)象自己(瀏覽器當(dāng)中是window)。任何一個(gè)函數(shù)上下文都有一個(gè)被稱為活動(dòng)對(duì)象的變量對(duì)象。(這個(gè)活動(dòng)對(duì)象取決于調(diào)用這個(gè)函數(shù)的執(zhí)行context)
var foo; //base value = window, reference name = foo;
function a() {
var b; // base value = ActivationObject
, reference name = b;
}
如果一個(gè)引用的基礎(chǔ)值是undefined的話,那么這個(gè)引用就被認(rèn)為unresolvable
因此,如果點(diǎn)號(hào)前面的值為undefined,那么這個(gè)屬性引用就是unresolved。下面的這個(gè)例子就會(huì)拋出一個(gè)ReferenceError的錯(cuò)誤,但是這并非是因?yàn)?b>TypeError在此之前就被拋出。這是因?yàn)橐粋€(gè)屬性的基礎(chǔ)值是屬于CheckObjectCoercible,當(dāng)試著將一個(gè)Undefined類型的轉(zhuǎn)化為一個(gè)Object,那么這種情況下會(huì)拋出TypeError;
var foo; foo.bar; //TypeError (base value, foo, is undefined) bar.baz; //ReferenceError (bar is unresolvable) undefined.foo //TypeError (base value is undefined)
如果使用var關(guān)鍵字,那么將會(huì)確保變量對(duì)象始終有基礎(chǔ)值,那么就不會(huì)出現(xiàn)引用變量unresolvable的情況。
當(dāng)引用被定義的時(shí)候既不是屬性值也不是變量的時(shí)候?qū)?huì)拋出一個(gè)ReferenceError:
foo; //ReferenceError
Javascript檢測(cè)到引用名foo沒有明確的基礎(chǔ)值,因此就會(huì)去尋找屬性名為foo的變量對(duì)象。沒有找到的話,就會(huì)認(rèn)為引用名foo沒有基礎(chǔ)值并拋出ReferenceError的錯(cuò)誤。
But isn"t foo just a undeclared variable?技術(shù)上來說不是。盡管有時(shí)候我們覺得undeclared variable是有利用我們?nèi)ヅ挪?b>bug。但是事實(shí)上如果一個(gè)變量未被聲明的話也就不是一個(gè)變量。
What about implicit globals?未通過var關(guān)鍵字聲明的標(biāo)識(shí)符將會(huì)默認(rèn)當(dāng)做全局變量而被創(chuàng)建,但這只會(huì)在這些標(biāo)識(shí)符被賦值的情況下才會(huì)生效。
function a() { alert(foo); // ReferenceError bar = [1, 2, 3]; // no error, bar is global } a(); bar; // [1, 2, 3]
這確實(shí)讓人有點(diǎn)困惑。如果Javascript檢測(cè)到unresolvable的引用就直接拋出ReferenceErrors就更好了。(事實(shí)上在嚴(yán)格模式下javascript確實(shí)是這樣做的)
When do I need to code against ReferenceErrors?如果你的代碼寫的很合理。我們發(fā)現(xiàn)在典型的用法中只有一種方式會(huì)遇到unresolvable reference: 當(dāng)使用屬性或者變量的句法不正確的時(shí)候。在大多數(shù)情況下,如果你能確保聲明變量的時(shí)候使用var關(guān)鍵字時(shí)即可避免這種情況。在代碼運(yùn)行過程中唯一可能會(huì)遇到的情況就是引用的變量?jī)H僅存在于部分瀏覽器或者第三方的代碼當(dāng)中。
一個(gè)比較好的例子就是console.在webkit瀏覽器中,console是內(nèi)置的,console這個(gè)屬性可以在任何地方獲取到。Firefox中console屬性取決于Firebug是否被安裝以及被打開使用。IE7下沒有console,IE8下的console屬性僅存在于IE Developer Tools被啟動(dòng)的情況下。Opera明顯是有console屬性的,但是我從來沒用使用過。
最后的結(jié)果就是,下面的代碼在瀏覽器中運(yùn)行時(shí)還是有可能會(huì)拋出ReferenceError的錯(cuò)誤。
console.log(new Date());How do I code against variables that may not exist?
一種方式就是去通過使用typeof關(guān)鍵字去嗅探一個(gè)unresolvable reference,避免拋出ReferenceError錯(cuò)誤:
if (typeof console != "undefined") { console.log(new Date()); }
然而這種方法對(duì)我來說太啰嗦了,更不用說合理了。我是比較反對(duì)使用typeof去進(jìn)行類型檢測(cè)的。
幸運(yùn)的是還有另外一種方式:我們已經(jīng)知道基礎(chǔ)值被定義了,但是屬性未被定義是不會(huì)拋出ReferenceError。console是全局對(duì)象的屬性值,因此我們可以這樣做:
window.console && console.log(new Date());
事實(shí)上在全局環(huán)境下僅僅只需要檢測(cè)變量是否存在(函數(shù)中也存在著執(zhí)行上下文,你可以決定哪些變量可以存在于你的函數(shù)當(dāng)中)。因此理論上至少你可以避免使用typeof來消除ReferenceError的情況。
原文鏈接
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/88087.html
摘要:生產(chǎn)者只能把消息發(fā)到交換器。是否要追加到一個(gè)特殊的隊(duì)列是否要追加到許多的隊(duì)列或者丟掉這條消息這些規(guī)則被定義為交換類型。有一點(diǎn)很關(guān)鍵,向不存在的交換器發(fā)布消息是被禁止的。如果仍然沒有隊(duì)列綁定交換器,消息會(huì)丟失。 發(fā)布與訂閱 (Publish/Subscribe) 在之前的章節(jié)中,我們創(chuàng)建了工作隊(duì)列,之前的工作隊(duì)列的假設(shè)是每個(gè)任務(wù)只被分發(fā)到一個(gè)worker。在這一節(jié)中,我們會(huì)做一些完全不一...
摘要:一篇簡(jiǎn)單的探索,這個(gè)嚴(yán)格模式出來很早了,很多人都有寫過,而且官方文檔很詳細(xì)。 原文鏈接:乖小鬼的簡(jiǎn)書 為什么想到寫這么一篇文章呢,來源在于回答一個(gè) SG上面的問題。那么問題是這樣子的。 var a = 2; function foo(){ console.log(this.a);} foo(); 以上代碼,執(zhí)行的結(jié)果是什么?? 如果你回答是2,那么對(duì)了多少? 只能說對(duì)了一半,為什么...
摘要:如果我們把非布爾值作為條件呢打開控制臺(tái)并運(yùn)行上述代碼,會(huì)打印說明條件為真值。在中,真值指的是在布爾值上下文中轉(zhuǎn)換后的值為真的值。兩個(gè)能夠建立元素間一一對(duì)應(yīng)的集合稱為互相對(duì)等集合。 showImg(https://segmentfault.com/img/bVbtSvt?w=720&h=360); 為了保證可讀性,本文采用音譯而非直譯。 Javascript 一直是神奇的語言。 不相信我...
摘要:本文不是標(biāo)準(zhǔn)的中文翻譯,也不是的入門教程,本文雖然以的常見問題切入,但并不適合想要快速了解這些問題的人才是快速了解問題的正解。盡量以英文原版為基礎(chǔ),為了流暢,可能會(huì)使用某些名詞的中文翻譯,但會(huì)將匹配的英文名詞以此種樣式中出現(xiàn)一次以避免誤解。 簡(jiǎn)單易懂的ECMA規(guī)范導(dǎo)讀1 序 最近混SF,恰巧又逢工作方面有了NodeJS的機(jī)會(huì),迫切地有教別人怎么寫JS的需求, 我發(fā)現(xiàn)JS這個(gè)東西其實(shí)...
閱讀 883·2021-11-22 12:04
閱讀 2088·2021-11-02 14:46
閱讀 616·2021-08-30 09:44
閱讀 2098·2019-08-30 15:54
閱讀 715·2019-08-29 13:48
閱讀 1587·2019-08-29 12:56
閱讀 3441·2019-08-28 17:51
閱讀 3279·2019-08-26 13:44