This question already has answers here:
Detecting an undefined object property
(50 answers)
Closed 5 years ago.
My question is about preventing an "variable is undefined" error more effiencitly.
e.g
If I use the following code:
if (array[index] != undefined)
{
if (array[index].id == 1)
{
// code
}
}
It will work fine. But, am I able to use
if (array[index] != undefined && array[index].id == 1)
{
// code
}
without getting an "variable is undefined" error, if array is undefined?
(I can't exactly test this in my code right now because I'm building a client-server application, and I'd have to alter many lines to try it, so I'm asking it here. I'm sorry if it's not appropriate)
&& will return true only if both the values of (a && b) a and b are truthy values.
If first operand(expression) is evaluated as false, second operand(expression) is not evaluated at all because the result would always be false
is better practice to use typeof to evaluate undefined variables:
if ( typeof array[index] !== 'undefined' && array[index].id == 1)
{
// code
}
Remember to check the string 'undefined' not the primitive value.
More info in MDN
No, if array is undefined, you will need an if statement that looks something like this:
if (array && array[index] !== undefined && array[index].id === 1) {
// do things
}
The first condition that if false will stop the evaluations of all the other conditions. The only way this will fail is if you are running you code in strict mode and have never declared var array
The if will return true only if all the conditions inside the paranthesis of if are true.
If any one of the expression is evaluated as false, The whole expression is evaluated as false.
If you have to check array itself is undefined then you will have to check typeof array also there. Something like this:
if(typeof array !== 'undefined'){
if ( typeof array[index] !== 'undefined' && array[index].id == 1)
{
// code
}
}
Yes, if the first condition fails, it will short-circuit and ignore the other conditions, like in any language.
Related
One annoying thing about writing js app is that nested object can caused error and break down the entire app.
if(result.applicant._id === null || applicant_id !== result.applicant._id.toString()){
console.log('redirect user');
}
Given above code, it can be dangerous, what if result.applicant._id is null? then toString will be invalid because it can't be undefined.toString(). How to ensure toString() work in this case? I can do
if(result.applicant._id === null || applicant_id !== (result.applicant._id && result.applicant._id.toString())){}
but that's so unclean. I found that I'll have many duplication just for the sake of checking something exist using js.
Your version works without ever hitting undefined.toString() because the if condition will be short-circuited (short-circuitted?) as result.applicant._id === null would evaluate as true and never evaluate applicant_id !== result.applicant._id.toString().
The test is already there no need to add extra checks in this case.
Update Just realised the === will not match undefined.
Just change the first part to result.applicant._id == null which will match undefined and null.
if (result.applicant._id == null || applicant_id !== result.applicant._id.toString()){
console.log('redirect user');
}
I know you may end with linting warnings but in this case that's exactly what you want.
A bit of short-handing might give you the cleaner code you're looking for.
As long as 0 is not a valid application id:
const id = result.application._id || 0;
if(!id || applicant_id !== id.toString()){
// redirect
}
Edit: To explain - the || in the variable declaration assigns the value to the first truthy value - or the second. Therefore, if the value is undefined, it will fall to the second value (0) which is still falsey and will fail the check, but can still have .toString() called on it.
Edit 2: If your ids are just numbers (which is what it looks like) then you actually don't need to convert it to a string - just let JavaScript's coercion to the work for you by using != instead of !==
const id = result.application._id || 0;
if(!id || applicant_id != id){
// redirect
}
In JavaScript, 12 == '12' is true. 12 === '12' is false. Generally the advice is to use === unless you consciously want to take advantage of coercion, and this seems like a good case for it :)
🏄 The shortest way could be this:
.: UPDATED :.
const applicant = result.applicant || {}
if (applicant_id !== `${applicant._id}`) {
console.log('redirect user');
}
I am using this "!!" comparation in order to compare with "undefined". However, is there any other way to do it?
isWidgetTemplatesLoaded: function(widgetName) {
return !!templates[widgetName];
}
Thanks
You could use typeof to check for undefined:
(typeof templates[widgetName] !== 'undefined')
typeof always returns a string. It returns "undefined" if the value of the variable is undefined or the variable does not exist.
You can use the typeof operator
typeof templates[widgetName];
else you can also use like this
if (templates[widgetName] === undefined) {
// rest of code
}
else {
// rest of code
}
To check for undefined you can just use the no-conversion equal/different operators:
if (x !== undefined) { ... }
if (y === undefined) { ... }
note however that this doesn't have the exact same meaning of !!. The double-negation for example returns true even for false, null, 0 or "" despite the fact that these values are not undefined.
By the way in Javascript you should basically always use === and !== instead of == and !=, unless you really need the crazy implicit conversion that equality/different operators do (and no one needs that). Good Javascript editors will warn you about any use of == or != as they are just bug-hiding places.
In the specific of your question code the !! logic seems wrong on a philosophical level because an empty template could be "" and this function would say that the template has not been loaded while instead it has been loaded and simply happens to be the empty string.
You could use the in operator, if you know, if the property exist with some value, other than undefined.
return widgetName in templates;
Learning about the typeof keyword and need some clarification:
While troubleshooting I outputted this code to the console:
console.log(typeof object.prop[someNum - 1]);
(in this case sumNum === 0)
The console printed out undefined which is what I expected because the index position [someNum - 1] in the prop[] array doesn't exist (so I thought).
However when I do something like this:
if(typeof object.prop[someNum - 1])
//some code
else
//other code
It evaluates as true and runs //some code but when I do this:
if(object.prop[someNum - 1])
//some code
else
//other code
It evaluates as false and runs //other code.
I was under the impression that undefined is considered a falsy valueand would evaluate false in an if statement. Why is the if(typeof object.prop[someNum - 1]) statement evaluating as as true? Also can someone point me in the right direction as to where I can learn more about negative indexing arrays in js? Are they handled the same across multiple languages like c#, c++, java, & php. I thought when evaluating a negative array index number it would be underfined or throw an error.
typeof always returns a string.
Therefore, you're writing if ("undefined").
Since non-empty strings are truthy, that if will run.
As SLaks says, you're evaluating if the string "undefined" is truthy, which it is.
If you want to see if an object has a property called "someNum - 1" then you can use the in operator:
if ((someNum - 1) in object.prop)
which will return true if object.prop has such a property anywhere on itself or its [[Prototype]] chain, or:
if (object.prop.hasOwnProperty(someNum - 1))
to test for the property directly on the object.
As other answers have pointed out, typeof returns a string, and it will always be truthy because it never returns an empty string. If you want to test if the type is undefined, you need to compare the string.
if (typeof object.prop[someNum - 1] == "undefined") {
// some code
} else {
// some code
}
You could also just test whether the value is undefined:
if (object.prop[someNum - 1] === undefined) {
// some code
} else {
// some code
}
Make sure you use === rather than ==, so it won't report a match if object[someNum - 1] is null.
I passed in a series of JSON objects with an AJAX call. Some of the data sets include the field C and some do not. When I include the following code, it crashes. I have tried undefined and null. Both crash.
if (myJsonObjects[i].C == undefined) {
// …
}
When you say crash I presume you mean TypeError: cannot read property of undefined value
The reason it crashes is because in the line
if(myJsonObjects[i].C == undefined){
We actually have myJSONObject[i] === undefined
So really you need to check your array bounds or make sure your array is not sparse
if(myJsonObjects[i].C == undefined){
is the similar as
if(myJsonObjects[i] && myJsonObjects[i].C){
but with mine line, you check is myJsonObjects[i] and myJsonObjects[i].c are null or undefined.
The caveat being if myJsonObjects[i].c holds false, "", 0, NaN
Try this:
if (typeof myJsonObjects[i].C == 'undefined') {}
I guess you could test the waters a little before jumping right in:
if( i in myJsonObjects && myJsonObjects[i] && !( "C" in myJsonObjects[i] ) ) { }
However your original code should not crash and shouldn't throw error either if myJsonObjects[i] is defined and is not null
How about
if ('C' in myJsonObjects[i]) { do_your_magic() }
I'm checking if(response[0].title !== undefined), but I get the error:
Uncaught TypeError: Cannot read property 'title' of undefined.
response[0] is not defined, check if it is defined and then check for its property title.
if(typeof response[0] !== 'undefined' && typeof response[0].title !== 'undefined'){
//Do something
}
Just check if response[0] is undefined:
if(response[0] !== undefined) { ... }
If you still need to explicitly check the title, do so after the initial check:
if(response[0] !== undefined && response[0].title !== undefined){ ... }
I had trouble with all of the other code examples above. In Chrome, this was the condition that worked for me:
typeof possiblyUndefinedVariable !== "undefined"
I will have to test that in other browsers and see how things go I suppose.
Actually you must surround it with an Try/Catch block so your code won't stop from working.
Like this:
try{
if(typeof response[0].title !== 'undefined') {
doSomething();
}
}catch(e){
console.log('responde[0].title is undefined');
}
typeof:
var foo;
if (typeof foo == "undefined"){
//do stuff
}
It'll be because response[0] itself is undefined.
Check if condition == null;
It will resolve the problem
Check if you're response[0] actually exists, the error seems to suggest it doesn't.
You must first check whether response[0] is undefined, and only if it's not, check for the rest. That means that in your case, response[0] is undefined.
I know i went here 7 months late, but I found this questions and it looks interesting. I tried this on my browser console.
try{x,true}catch(e){false}
If variable x is undefined, error is catched and it will be false, if not, it will return true. So you can use eval function to set the value to a variable
var isxdefined = eval('try{x,true}catch(e){false}')
In some of these answers there is a fundamental misunderstanding about how to use typeof.
Incorrect
if (typeof myVar === undefined) {
Correct
if (typeof myVar === 'undefined') {
The reason is that typeof returns a string. Therefore, you should be checking that it returned the string "undefined" rather than undefined (not enclosed in quotation marks), which is itself one of JavaScript's primitive types. The typeof operator will never return a value of type undefined.
Addendum
Your code might technically work if you use the incorrect comparison, but probably not for the reason you think. There is no preexisting undefined variable in JavaScript - it's not some sort of magic keyword you can compare things to. You can actually create a variable called undefined and give it any value you like.
let undefined = 42;
And here is an example of how you can use this to prove the first method is incorrect:
https://jsfiddle.net/p6zha5dm/