2011-06-28 12 views
22

Jestem doświadczonym programistą C++/Java pracującym w JavaScript po raz pierwszy. Używam Chrome jako przeglądarki.Wymuś wyjątek/błąd JavaScript podczas odczytu niezdefiniowanej właściwości obiektu?

Stworzyłem kilka klas JavaScript z polami i metodami. Kiedy czytam pole obiektu, które nie istnieje (z powodu literówki z mojej strony), środowisko wykonawcze Javascript nie generuje błędu ani wyjątku. Najwyraźniej takie pola odczytu są "niezdefiniowane". Na przykład:

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

wiem, że mogę sprawdzić dla równości wobec „niezdefiniowane” jak wspomniano w „Detecting an undefined object property in JavaScript”, ale to wydaje się nudny ponieważ czytałem z pól obiektów Często w moim kodu.

Czy istnieje sposób wymuszenia na wystąpieniu błędu lub wyjątku podczas odczytu niezdefiniowanej właściwości?

Dlaczego zgłasza się wyjątek podczas odczytu niezdefiniowanej zmiennej (w przeciwieństwie do niezdefiniowanej właściwości obiektu)?

+0

Wystarczy popatrzeć na proxy JavaScript. – nalply

Odpowiedz

13

Wydaje mi się, że to klasyczny przypadek, w którym próbuje się dopasować jeden język do paradygmatów innego - lepszego IMHO, aby zmienić styl kodowania, tak aby postępować zgodnie z tym, co robi JavaScript, niż próbować dostosować go do koncepcji i oczekiwań w C++.

To powiedziawszy, jeśli chcesz rzucić błąd, jak sugerujesz, musisz zdefiniować jakąś niestandardową funkcję getProperty, albo na obiekcie, do którego próbujesz uzyskać dostęp, albo w zasięgu globalnym. Implementacja może wyglądać następująco:

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 

Ale to brzydkie, a teraz masz zwyczaj ten język skonstruować w całym kodzie, co czyni go mniej przenośne (jeśli na przykład chcesz skopiować dowolny część twojego kodu do innego skryptu, musisz też skopiować twoją nową funkcję) i mniej czytelną dla innych programistów. Więc naprawdę polecam pracę w ramach paradygmatu Javascript i sprawdzanie dla undefined przed uzyskaniem dostępu do potrzebnych właściwości (lub ustawienia kodu tak, aby oczekiwano wartości false-y i nie psują rzeczy).

Co do twojego drugiego pytania, dlaczego JavaScript zgłasza błąd dla niezdefiniowanych zmiennych, ale nie dla niezdefiniowanych właściwości obiektu, nie mogę dać żadnej lepszej odpowiedzi niż "ponieważ to jest to, co jest w specyfikacji języka." Objects return undefined for undefined property names, ale undefined variable references throw an error.

+24

Całkowicie się mylisz. Nie ma tu nic do "buthorn". Klasy C i klasy C++/C#/Java zachowują się poprawnie: Jeśli spróbujesz odczytać pole, które nie istnieje, kompilator zgłosi błąd. To nie jest ekscentryczność powyższych języków; to także po prostu zdrowy rozsądek. – stackoverflowuser2010

+9

@ stackoverflowuser2010 - Moja opinia jest tutaj nieistotna, ale wyraźnie projektanci ECMAScript/Javascript nie zgadzają się z tobą. Równie dobrze możesz twierdzić, że JavaScript nie jest zgodny z "zdrowym rozsądkiem", ponieważ jest luźno wpisany. – nrabinowitz

+1

Całkowicie zgadzam się z terminem "łyżka do butów" i argumentami. Jednak (konkretny przypadek tutaj!) W kontekście .net, możesz użyć technologii T4 do autogeneracji właściwości accessorów (automatyczne generowanie jednostek w javascript z pliku edmx jest dobrym przykładem, jak sądzę). W ten sposób kod jest "mniej brzydki", ponieważ ta część kodu staje się po prostu czarną skrzynką i może rozwiązać problem. –

0

Czy istnieje sposób wymuszenia na wystąpieniu błędu lub wyjątku podczas odczytu niezdefiniowanej właściwości?

W skrócie, nie. Zawsze można przetestować, czy ty skończył z nieokreślone albo przez porównanie do undefined, jak pan powiedział, albo próbuje uzyskać dostęp do drugiego atrybutu Level:

s = Foo() 

s.bar = 1 

s['Bar'] // returns undefined. 

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

Dodatkowo undefined zawodzi w czeku warunkowym, więc można uciec z tego jako skrót dla porównania:

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

mieć świadomość, że ten krótki ręka może spowodować nieoczekiwane zachowanie jeśli s [ „bar”] został ustawiony, ale była wartość „Falsey”, a ty dotyczyły tylko tego, czy wróciło ono niezdefiniowane.

+0

I, jak wskazuje inna odpowiedź, przyczyną niezdefiniowania brakujących atrybutów, ale błąd w przypadku niezadeklarowanych zmiennych, jest specyfikacja języka JavaScript. –

4

Firefox ma opcję javascript.options.strict (w about:config). Po włączeniu tego ostrzeżenia będą rejestrowane do konsoli dla wielu typowych błędów, w tym czytania niezdefiniowanej właściwości, używając = zamiast == w if itp

(oczywiście, że nie znaczy taki kod jest koniecznie źle.)

2

Czy istnieje sposób wymuszenia na wystąpieniu błędu lub wyjątku, gdy odczytuje niezdefiniowaną właściwość?

Jest to możliwe przy użyciu serwerów proxy ES6, jak wspomniano w poprzednich odpowiedziach. Zrobiłem mały moduł węzłowy "zealit", aby uniknąć konieczności zaimplementowania go za każdym razem.

Jeśli ktoś jest zainteresowany: 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

ten może zostać osiągnięty za pomocą 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

Powiązane problemy