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