3

Say I have some object

> var a = {'a': 1, 'b': 2}
undefined
> a.c
undefined

I would like it if this "undefined" attribute c were to instead raise some sort of custom error.

Is there some way to over-ride my object's default behavior, or perhaps invoke it in some way as to provide a callback in case the lookup returns undefined?

I found this question from a couple of years ago that appears related.

I ask because I feel generic TypeError: cannot call method 'foo' of undefined errors might be better replaced with more meaningful feedback.

Community
  • 1
  • 1
yurisich
  • 6,991
  • 7
  • 42
  • 63
  • 3
    Maybe this question helps: http://stackoverflow.com/q/2756431 Or possibly some hack with `get` (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/get) – gen_Eric Dec 30 '13 at 18:24
  • +1 for getters/ setters. – AlbertEngelB Dec 30 '13 at 18:37
  • 1
    See http://stackoverflow.com/questions/2266789/is-there-an-equivalent-of-the-nosuchmethod-feature-for-properties-or-a-way – Pedro Rodrigues Dec 30 '13 at 19:00
  • @RocketHazmat + PedroRodrigues hit the nail on the head I can't believe I didn't think that deep into it. Wish I could give y'all rep for those two comments. – Deryck Dec 30 '13 at 20:46

4 Answers4

1

You'll be testing for an error one way or another. Overriding it doesn't make a lot of sense, especially since you'll just make your code base more complicated and undefined actually makes sense here. The property c is literally undefined and so this is quite readable (especially to new people working with your code):

if (a.c) { //or could be a.c !== undefined, 
           //but if(a.c) will catch other falsey values
    a.c.something();
}
Mike Thomsen
  • 36,828
  • 10
  • 60
  • 83
1

You can use try, throw and catch() for this is exact situation.

Here's an example:

var a = {'a': 1,'b': 2};
try {
    if (a.c === undefined) throw "Sorry you need to create the property 'a.c first";
} catch (err) {
    console.log(err);
}

In JS Fiddle

Whatever you put as the string after throw becomes the argument passed to catch(err). So, instead of it saying undefined it says Sorry you need to create the property 'a.c first

Deryck
  • 7,608
  • 2
  • 24
  • 43
  • 1
    Not a solution actually. it still gives `undefined` for `a.c` in console if you run the whole code in console. The OP asked for the feedback to be customized and this one definitely isn't what he wanted. – Rajesh Paul Dec 30 '13 at 19:28
  • That's because if you use it in the console, the `try` and `catch` are treated separately from the processing of the actual `throw`. I know that's not the correct way of explaining it but to see what I mean, all you have to do is use the `if (typeof a.c === 'undefined') throw "Sorry you need to create the property 'a.c first";` code itself in console without utilizing `try` / `catch`. This will result in the desired effect. What my answer is useful for is debugging an actual web application in the browser. However, you are correct in that I strayed from the posed question, my apologies. – Deryck Dec 30 '13 at 20:41
  • PS - even though my answer has a use-case for individual **KNOWN** objects/properties, I really wish I had thought further into it and mentioned `get` as the real way to intercept these. I fully support the comments on the main post above referring to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/get as the best route to achieving this goal. – Deryck Dec 30 '13 at 20:49
0

If you want to get a more meaningful feedback, you can use Firefox.

At least on its version 26, I get

TypeError: a.c is undefined

when doing

var a = {};
a.c.foo(); // TypeError: a.c is undefined
Oriol
  • 274,082
  • 63
  • 437
  • 513
0

There's a js library called underscore.js with methods like _.isUndefined(), _.isNull(), _.isEmpty() or _.isNan() that may be useful for you in some case.

But the way javascript capture exceptions is like Deryck said. Anyway I'd prefer have more control throw if validations with the underscore methods when I need it.

fray88
  • 820
  • 1
  • 7
  • 23