- Force JavaScript exception/error when reading an undefined object property?
- 7 Answers 7
- Javascript: is it safe to «throw undefined»?
- 2 Answers 2
- Handling error message of ‘undefined’ in javascript
- 1 Answer 1
- Throw an error if undefined?
- 4 Answers 4
- UPDATE
- How to handle ‘undefined’ in JavaScript [duplicate]
- 3 Answers 3
Force JavaScript exception/error when reading an undefined object property?
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 fields and methods. When I read an object’s field that doesn’t exist (due to a typo on my part), the Javascript runtime doesn’t throw an error or exception. Apparently such read fields are ‘undefined’. For example:
var foo = new Foo(); foo.bar = 1; var baz = foo.Bar; // baz is now undefined
I know that I can check for equality against ‘undefined’ as mentioned in «Detecting an undefined object property in JavaScript», but that seems tedious since I read from object fields often in my code. Is there any way to force an error or exception to be thrown when I read an undefined property? And why is an exception thrown when I read an undefined variable (as opposed to undefined object property)?
This won’t answer this question (stop reading undefined properties), but if you’d like to prevent accidentally creating a new property by a typo (e.g. if you do foo.barr = 1 this creates a new property barr). So if you’d like to stop that, you can call Object.preventExtensions(foo); and use it together with ‘strict mode’ — should throw a type error.
I would suggest you to have a look at my answer and mark it as accepted if you find it satisfactory. I was having the same problem as well and currently, that’s the most straightforward, non-hacky (clean) solution to overcome this problem.
7 Answers 7
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 '$' 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
This has some unfortunate side effects, as it won’t work when inspecting the object (e.g., when running through a REPL or using console.log ).
This is great! If you’d also like to prevent creating new properties by accident, set: Object.preventExtensions(noUndefObj); and use strict mode
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.
Javascript: is it safe to «throw undefined»?
In the function below, when the condition fails I want the situation to be handled as a simple error (no details needed). Just out of curiosity, is it OK and safe to write throw undefined ?
function splitYearMonth (YM) < // Returns ["yyyy-mm", yyyy, mm] try < var o = YM.match(/^(\d)\-(02|1[012])$/); if (o != null) < return [o[0], parseInt(o[1], 10), parseInt(o[2], 10)]; >else < throw undefined; >> catch (e) < return [undefined, undefined, undefined]; >>
Never mind the example given. Basically my (idle) question is just: I don’t care about the error I’m throwing, I’m tempted to throw undefined because it seems to make more sense that any other type of specific value, and I want to know if that’s safe.
2 Answers 2
The ECMAScript 5.1 specification says:
- Let exprRef be the result of evaluating Expression.
- Return (throw, GetValue(exprRef), empty).
undefined is definitely an expression, so it can be thrown. You can see an example in this fiddle.
That said, throwing undefined may not be a good idea from a maintainability standpoint, because doing so leaves you with no information at all about the cause of the exception. Throwing a string would arguably be a better solution:
var o = YM.match(/^(\d)\-(06|1[012])$/); if (o != null) < return [o[0], parseInt(o[1], 10), parseInt(o[2], 10)]; >else
Update: On second thought, unless the no details needed clause in your question means you’re not telling us the whole story, you only need control flow, not exception handling. You only have to write:
function splitYearMonth(YM) < // Returns ["yyyy-mm", yyyy, mm] var o = YM.match(/^(\d)\-(04|1[012])$/); if (o != null) < return [o[0], parseInt(o[1], 10), parseInt(o[2], 10)]; >else < return [undefined, undefined, undefined]; >>
Exception handling can be expensive, and it is usually not recommended to use this facility for control flow (since we’re discussing Javascript and not, say, Python).
Handling error message of ‘undefined’ in javascript
As I can see in almost case, javascript would throw message undefined or x is not defined , etc. Here is some:
var i; var j = i; alert(j); // undefined var xyz; alert(xyz); // undefined
alert(xyz); // Uncaught ReferenceError: xyz is not defined // or alert(xyz === undefined); // Uncaught ReferenceError: xyz is not defined
alert(typeof(xyz) === 'undefined'); // true
So, the problem is: you want to get the type of nothing . If something is-a thing (not nothing ), the type should be an attribute of that. You can assign it after declaring, and only. My question: how is my idea to handle that error messages? p/s: I come from C# 🙂
I’m not really sure what you are asking here, but it seems that you want to have a discussion about redesigning a fundamental part of the JavaScript language. This isn’t the right place for that.
1 Answer 1
There are two concepts at play here:
- An identifier that is not defined (completely undeclared, doesn’t exist in the current scope at all)
- An identifier that is defined (is declared, is in scope) that contains the value undefined
The short answer is: If you want to see if an identifier is currently in scope which may or may not be in scope, do this:
typeof xyz will never throw an error, even if xyz is completely undeclared. This is (as you’ve found) different from xyz === undefined , which will throw a ReferenceError if xyz is a completely undeclared identifier.
No, it’s defined without a default value. So, the error message should be:
Use of unassigned local variable 'i'
Use of unassigned local variable 'xyz'
JavaScript has no concept of an unassigned variable. When a variable is created, it is automatically assigned the value undefined .
Throw an error if undefined?
Is there a way to throw an error if property could not be found from data . Problem is, it is mapping undefined instead of throwing error.
const insertIntoTable = function(data) < return new Promise((resolve, reject) => < const entry = < Id: data.id, Method: data.Method, Status: data.PaymentStatus, InsertedAt: (new Date().getTime()) >>).catch((error) => < console.log(error); >); >
You have to check each property manually e.g. if (data.id === undefined) throw new Error(«mapping undefined») Also call resolve/reject to resolve the promise.
You create an entry but then throw it away. Because you never use it for anything (for example return it). You also never resolve your promise.
Well doing .catch((error) => < console.log(error); >); suppresses any error and fulfills with undefined instead. Just remove that part from your code completely.
4 Answers 4
You can check if the properties are undefined by comparing it to undefined . For example, if you wanted to check the id property, you could use
const insertIntoTable = function(data) < return new Promise((resolve, reject) => < if(data.id)< const entry = < Id: data.id, Method: data.Method, Status: data.PaymentStatus, InsertedAt: (new Date().getTime()) >return resolve(entry); > return reject(); >) .then((data) => < // treat your entry data >) .catch(() => < throw new Error("data is undefined") >); >
There is no need to return resolve or reject , besides OP wants to check individual properties, not just data
From my understanding of promises, you aren’t post to return resolve or reject . You just call them. Why do you return them?
@TruongDang It appears that it does change how the code works. According to this post, a return halts the function. Without it, the function can continue going on. Interesting.
First you need to correctly start your Promise, since you are not resolving it, I like to do it like so:
const insertIntoTable = function(data) < return Promise.resolve() .then(() => < const entry = < Id: data.id, Method: data.Method, Status: data.PaymentStatus, InsertedAt: (new Date().getTime()) >// Do something with entry >) .catch((error) => < console.log(error); >); >
This way you can throw inside you validation (instead of rejecting)
You could create a validation function that checks for undefined, like so:
But this way you would always get the same error. You could change it to show an error based on the property name:
const getAndValidate = (data, propertyName) =>
This way you get the right error everytime, but I don’t like to access the attributes using string names
One way of doing it would be to take advantage of the short-circuit evaluation, and do something like:
const insertIntoTable = function(data) < return new Promise((resolve, reject) => < const entry = < Id: data.id || reject("data.id is undefined"), Method: data.Method || reject("data.Method is undefined"), Status: data.PaymentStatus || reject("data.PaymentStatus is undefined"), InsertedAt: (new Date().getTime()) >resolve(entry); >).catch((error) => < console.log(error); >); > insertIntoTable(<>).then(data => console.log(data));
However, I find this hard to read, so I’m currently looking for a better alternative.
UPDATE
I had been working on a function using proxies that provides an optional or default behavior, the function is
function optional(obj, evalFunc, def) < // Our proxy handler const handler = < // Intercept all property access get: function(target, prop, receiver) < const res = Reflect.get(. arguments); // If our response is an object then wrap it in a proxy else just return return typeof res === "object" ? proxify(res) : res != null ? res : def; >>; const proxify = target => < return new Proxy(target, handler); >; // Call function with our proxified object return evalFunc(proxify(obj, handler)); >
And could be applied here as
const insertIntoTable = function(data) < return new Promise((resolve, reject) => < const entry = < Id: optional(data, t =>t.Id, reject('Id is not present')), Method: optional(data, t => t.Method, reject('Method is not present')), Status: optional(data, t => t.PaymentStatus, reject('PaymentStatus is not present')), InsertedAt: (new Date().getTime()) > resolve(entry); >).catch((error) => < console.log(error); >); > insertIntoTable(<>).then(data => console.log(data));
The advantage this has is that it supports deep properties access.
How to handle ‘undefined’ in JavaScript [duplicate]
this jsVar is declared and initialized in another file. The problem is that code throws undefined error when this code is executed before the other file (where its declared and initialized) is executed. That is why it is surrounded by try and catch. What’s the best way to handle this undefined error than try catch?
I don’t get it, How come even after marked as duplicate this question still got 48 up votes. Isn’t it’s lack of judgement and decreases quality of these up votes. And then voting might be broke if duplicate questions get up votes.
3 Answers 3
You can check the fact with
if (typeof jsVar == 'undefined')
It may throw an error: jsVar is not defined. You should test it this way : if (window.jsVar !== undefined) <>. It seems like typeof() «catches» this error.
@Fabien: Or perhaps use if(«jsVar» in window)<>. but I would avoid code that would require coding for this error case.
@logic-unit that is in theory better, but == is enough for a typeof comparission, since there are only a few possible values that can be returned.
You can use the typeof to determine the type of the unevaluated operand. It will return the type of operand in a string. You can use «===», if you know they are equal value and equal type.
As is often the case with JavaScript, there are multiple ways to do this:
typeof foo !== 'undefined' window.foo !== undefined 'foo' in window
The first two should be equivalent (as long as foo isn’t shadowed by a local variable), whereas the last one will return true if the global varible is defined, but not initialized (or explicitly set to undefined ).
hmm ‘foo’ in windows seems to return false even if foo is defined for me, in fact only typeof seems to work in my case
In JavaScript, the following values will cause the if condition to fail and not execute its statement: null, undefined, false, NaN, the number 0, and the empty string ».
Assuming that the variable jsVar is a boolean and that we want to call the proceed() method when jsVar is true, we can do the following check.
The above code snippet first check that jsVar has been defined and then checks that its value is true. The if condition will be satisfied only if both the conditions are met.
If jsVar is not a boolean then we can substitute the appropriate check in place of jsVar == true in the code above.