Force JavaScript exception/error when reading an undefined object property?

后端 未结 7 1066
后悔当初
后悔当初 2020-11-30 04:29

I\'m an experienced C++/Java programmer working in Javascript for the first time. I\'m using Chrome as the browser.

I\'ve created several Javascript classes with fie

相关标签:
7条回答
  • 2020-11-30 05:04

    As of now, the "right" solution to this is to use TypeScript (or another type-checking library such as Flow). Example:

    const a = [1,2,3];
    
    if (a.len !== 3) console.log("a's length is not 3!");
    

    On JavaScript, this code will print "a's length is not 3!". The reason is that there is no such property len on arrays (remember that you get the length of an array with a.length, not a.len). Hence, a.len will return undefined and hence, the statement will essentially be equal to:

    if (undefined !== 3) console.log("a's length is not 3!");
    

    Since undefined is indeed not equal to 3, the body of the if statement will be run.

    However, on TypeScript, you will get the error Property 'len' does not exist on type 'number[]' right on the "compile time" (on your editor, before you even run the code).

    Reference

    0 讨论(0)
  • 2020-11-30 05:10

    Is there any way to force an error or exception to be thrown when I read an undefined property?

    In short, no. You can always test for whether or not you ended up with undefined by either comparing to undefined, like you said, or by attempting to access a second level attribute:

    s = Foo()
    
    s.bar = 1
    
    s['Bar'] // returns undefined.
    
    s['Bar']['Baz'] // Throws TypeError, s.Bar is undefined.
    

    Additionally, undefined fails in a conditional check, so you can get away with this as a shorthand for the comparison:

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

    Be aware that this short hand could cause unexpected behavior if s['Bar'] was set, but was a 'Falsey' value, and you were only concerned with whether or not it came back undefined.

    0 讨论(0)
  • 2020-11-30 05:18

    Is there any way to force an error or exception to be thrown when I read an undefined property?

    That's possible using ES6 proxies as has been said in previous responses. I have done the small node module "zealit" to avoid having to implement it every time.

    If someone is interested : 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 
    
    0 讨论(0)
  • 2020-11-30 05:18

    There is great power in consistency (like in the STL from Alexander Stepanov that Stroustrup adopted into C++). One simple reason for the inconsistent treatment of undeclared properties vs undeclared variables is probably a reflection of the thought and effort that went into evolving the different languages and another is probably the abilities of the people involved.

    It also impacts the kind of applications you would entrust to any given language. You hopefully wouldn't try to write mission critical software that runs a multimillion dollar cruise liner engine management system in javascript, for example.

    (Probably not a popular answer for javascript aficionados.)

    0 讨论(0)
  • 2020-11-30 05:22

    This looks to me like a classic case of trying to shoehorn one language into the paradigms of another - better IMHO to change your coding style to follow how Javascript does things than try to make it conform to C++ concepts and expectations.

    That said, if you want to throw an error as you suggest, you'll need to define some sort of custom getProperty function, either on the object you're trying to access or in the global scope. An implementation might look like this:

    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
    

    But this is ugly, and now you've got this custom language construct in all of your code, making it less portable (if, for example, you wanted to copy any part of your code into another script, you'd have to copy your new function too) and less legible to other programmers. So I'd really recommend working within the Javascript paradigm and checking for undefined before accessing the properties you need (or setting up your code so that false-y values are expected and don't break things).

    As to your second question, why Javascript throws an error for undefined variables but not for undefined object properties, I can't give any better answer than "Because that's what's in the language specification." Objects return undefined for undefined property names, but undefined variable references throw an error.

    0 讨论(0)
  • 2020-11-30 05:22

    This can be achieved using 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

    0 讨论(0)
提交回复
热议问题