2011-06-28 46 views
22

我是第一次在Javascript中工作的經驗豐富的C++/Java程序員。我使用Chrome作爲瀏覽器。閱讀未定義的對象屬性時強制執行JavaScript異常/錯誤?

我用字段和方法創建了幾個Javascript類。當我讀取一個不存在的對象字段時(由於我的錯字),Javascript運行時不會拋出錯誤或異常。顯然這樣的讀取字段是'未定義的'。例如:

var foo = new Foo(); 
foo.bar = 1; 
var baz = foo.Bar; // baz is now undefined 

我知道,我可以檢查針對如「Detecting an undefined object property in JavaScript」提到「未定義」平等,但因爲我從我的代碼往往對象字段閱讀似乎有些單調乏味。

當我讀取一個未定義的屬性時,有什麼辦法強制拋出錯誤或異常嗎?

爲什麼當我讀取一個未定義的變量(而不是未定義的對象屬性)時拋出異常?

+0

看一看的JavaScript代理。 – nalply

回答

13

這看起來像一個試圖將一種語言強加於另一種語言的經典案例 - 更好的恕我直言改變你的編碼風格,以跟隨Javascript如何做事,而不是試圖使它符合C++概念和期望。這就是說,如果你想按照你的建議拋出一個錯誤,你需要定義一些自定義getProperty函數,無論是在你試圖訪問的對象上,還是在全局範圍內。一個實現可能是這樣的:

function getProperty(o, prop) { 
    if (o.hasOwnProperty(prop)) return o[prop]; 
    else throw new ReferenceError('The property ' + prop + 
     ' is not defined on this object'); 
} 

var o = { 
    foo: 1, 
    bar: false, 
    baz: undefined 
}; 

getProperty(o, 'foo'); // 1 
getProperty(o, 'bar'); // false 
getProperty(o, 'baz'); // undefined 
getProperty(o, 'foobar'); 
// ReferenceError: The property baz is not defined on this object 

但這是醜陋的,現在你已經有了這個自定義語言,所有的代碼構造,使其便攜性較差(如果,例如,你想複製任何你的代碼的一部分插入到另一個腳本中,你必須複製你的新函數),而對其他程序員不太清晰。所以我真的推薦在Javascript範例中工作,並在訪問你需要的屬性(或設置你的代碼,以便預期false-y值不會中斷)之前檢查undefined

至於你的第二個問題,爲什麼Javascript會爲未定義的變量拋出一個錯誤,而不是未定義的對象屬性,我不能給出比「因爲這是語言規範中的內容」更好的答案。 Objects return undefined for undefined property names,但undefined variable references throw an error

+24

你完全錯了。沒有什麼可以在這裏「鞋拔」。 C結構和C++/C#/ Java類都行得通:如果你試圖讀取一個不存在的字段,編譯器會拋出一個錯誤。這不是上述語言的一些偏心;這也僅僅是常識。 – stackoverflowuser2010

+9

@ stackoverflowuser2010 - 我的看法與此無關,但顯然ECMAScript/Javascript設計師不同意你的看法。你可能會聲稱Javascript不遵循「常識」,因爲它是鬆散類型的。 – nrabinowitz

+1

完全同意「shoehorn」的術語和論點。然而,在.net上下文中(具體的情況!),你可以使用T4技術來自動生成屬性訪問器(我認爲在edmx文件中的javascript實體自動生成是一個很好的例子)。這樣,代碼「不那麼難看」,因爲這部分代碼只是變成了黑盒子,可以解決問題。 –

0

當我讀取一個未定義的屬性時,有什麼辦法強制拋出錯誤或異常嗎?

總之,沒有。你隨時可以測試你是否結束了不確定的或者比較undefined,就像你說的,或在嘗試訪問第二級屬性:

s = Foo() 

s.bar = 1 

s['Bar'] // returns undefined. 

s['Bar']['Baz'] // Throws TypeError, s.Bar is undefined. 

此外,undefined未能在條件檢查,所以你可以用這個逃脫作爲比較的簡寫:

if (s['Bar']) { 
    // Something here only if s['Bar'] is set. 
} 

注意,如果s [「酒吧」]設置這短短的手可能會導致意外的行爲,而是一個'Falsey的價值,和你只關心它是否返回undefined。

+0

而且,正如其他答案所指出的那樣,您對未找到的屬性未定義但未聲明的變量出錯的原因歸因於JavaScript語言規範。 –

4

Firefox有一個選項javascript.options.strict(在about:config)。如果啓用此,警告將被記錄到控制檯了很多常見的錯誤,包括讀取未定義的屬性,在if使用=代替==

(當然,這並不是說這樣的代碼是必然錯誤)。

2

當我讀取一個未定義的屬性時,有什麼辦法強制引發錯誤或異常嗎?

這是可能的使用ES6代理,如在以前的答覆中所述。 我已經完成了小節點模塊「zealit」以避免每次都需要實現它。

如果有人有興趣: https://www.npmjs.com/package/zealit

const zealit = require('zealit') 

const ref = { foo: true, bar: undefined } 
ref.foo // true 
ref.bar // undefined 
ref.baz // undefined 

const zealed = zealit(ref) 
zealed.foo // true 
zealed.bar // undefined 
zealed.baz // throws a ReferenceError 
6

這可以使用ES6 proxies實現:

function disallowUndefinedProperties(obj) { 
 
    const handler = { 
 
     get(target, property) { 
 
      if (property in target) { 
 
       return target[property]; 
 
      } 
 

 
      throw new Error(`Property '${property}' is not defined`); 
 
     } 
 
    }; 
 

 
    return new Proxy(obj, handler); 
 
} 
 

 
// example 
 
const obj = { key: 'value' }; 
 
const noUndefObj = disallowUndefinedProperties(obj); 
 

 
console.log(noUndefObj.key); 
 
console.log(noUndefObj.undefinedProperty); // throws exception

相關問題