Below is the piece of code I'm having a problem with. I get the JShint "Expected an assignment or function and instead saw an expression".
function checkVal(inputField) {
( inputField.val() === '' ) ? inputField.prev('.cd-label').removeClass('float') : inputField.prev('.cd-label').addClass('float');
}
});
The warning is telling you that the following line could be a mistake or bug:
( inputField.val() === '' ) ? inputField.prev('.cd-label').removeClass('float') : inputField.prev('.cd-label').addClass('float');
Its an expression using the ternary operator that returns the value after the ? if the expression before it is true, or the value after the : otherwise. So basically, it's like a shorthand if statement that results in an assignment.
To remove the warning, you need to assign it to a variable like this:
var yourVariable = ( inputField.val() === '' ) ? inputField.prev('.cd-label').removeClass('float') : inputField.prev('.cd-label').addClass('float');
However, for your case you probably don't really want to assign this to anything, so you should just use an if statement instead.
You should be using an if block here.
if( inputField.val() === '' ){
inputField.prev('.cd-label').removeClass('float');
}
else{
inputField.prev('.cd-label').addClass('float');
}
The ternary operator (?:) should only be used in a context where it returns a value. Such as:
var x = condition ? 'a' : 'b';
Related
I have a function which parses the address components of the Google Maps API JSON and then returns the city / locality / route name.
The getAddressComponent() returns a null if it cannot find the key.
let route = getAddressComponent(addressComponents, 'route').value.long_name;
So let's say it didn't find the key, then I get a Error: TypeError: Cannot read property 'long_name' of undefined obviously because it's not defined.
How do I check for null in javascript other than the conditional method (a === null)?
How can I simply check like this with ?
EDIT : Safe Navigation Operator
let route = getAddressComponent(addressComponents, 'route')?.value.long_name;
And if it doesn't exists, it could probably set route to null instead of throwing a Error ?
2020 Answer, It Exists!!!
You can now directly use ?. inline to test for existence. It is called the Optional Chaining Operator, supported by all modern browsers.
If a property exists, it proceeds to the next check, or returns the value. Any failure will immediately short-circuit and return undefined.
const example = {a: ["first", {b:3}, false]}
example?.a // ["first", {b:3}, false]
example?.b // undefined
example?.a?.[0] // "first"
example?.a?.[1]?.a // undefined
example?.a?.[1]?.b // 3
domElement?.parentElement?.children?.[3]?.nextElementSibling
To ensure a default defined value, you can use ??. If you require the first truthy value, you can use ||.
example?.c ?? "c" // "c"
example?.c || "c" // "c"
example?.a?.[2] ?? 2 // false
example?.a?.[2] || 2 // 2
If you do not check a case, the left-side property must exist. If not, it will throw an exception.
example?.First // undefined
example?.First.Second // Uncaught TypeError: Cannot read property 'Second' of undefined
?. Browser Support - 94%, Oct '22
?? Browser Support - 94%
Node Support - v14+
Update 2020
This long-wished feature is now available in JavaScript!
I'll redirect to Gibolt's answer, which covers it well.
Original 2018 answer
There is no "null-safe navigation operator" in Javascript (EcmaScript 5 or 6), like ?. in C#, Angular templates, etc. (also sometimes called Elvis operator, when written ?:) , at least yet, unfortunately.
You can test for null and return some dependent expression in a single line with the ternary operator ?:, as already given in other answers :
(use === null to check only for nulls values, and == null to check for null and undefined)
console.log(myVar == null ? myVar.myProp : 'fallBackValue');
in some cases, like yours, when your variable is supposed to hold an object, you can simply use the fact that any object is truthy whereas null and undefined are falsy values :
if (myVar)
console.log(myVar.myProp)
else
console.log('fallbackValue')
You can test for falsy values by coalescing to boolean with !! and make this inline :
console.log(!!myVar ? myVar.myProp : 'fallbackValue');
Be very careful though with this "falsy test", for if your variable is 0, '', or NaN, then it is falsy as well, even though it is not null/undefined.
Code below simplified return num ? num : 0 for me:
return num || 0;
As of today more correct semantically;
return num ?? 0
let component = getAddressComponent(addressComponents, 'route');
let route = component ? component : null
you can use the ? operator to check the value is true or false then set the value in javascript null will be false
For empty strings you can use !:
var foo = 'yo';
console.log(!foo);
var foo = null;
console.log(!foo);
And for the ? you asked about, it's the Conditional (ternary) Operator, the syntax is condition ? if true : if false you can use it as follows:
var foo = 'yo';
console.log('1 : ' + (!foo ? 'Null' : 'Not Null'));
console.log('2 : ' + (foo === null ? 'Null' : 'Not Null'));
console.log('3 : ' + (foo == null ? 'Null' : 'Not Null'));
var foo = null;
console.log('1 : ' + (!foo ? 'Null' : 'Not Null'));
console.log('2 : ' + (foo === null ? 'Null' : 'Not Null'));
console.log('3 : ' + (foo == null ? 'Null' : 'Not Null'));
What you want is a null coalescent operator.
Javascript doesn't have one. Most of the time peoples use the logical OR || for this purpose but it doesn't work on property access.
There's proposal for adding null coalescing to the language, but it's nowhere near:
https://github.com/tc39/proposal-nullish-coalescing
https://tc39.github.io/proposal-nullish-coalescing/
If you really, really, absolutly want to use it you can use this Babel plugin:
https://www.npmjs.com/package/babel-plugin-transform-optional-chaining
But I would strongly suggest you don't: this may never make it to the language and you would have unvalid code in your codebase.
.? cannot be used in javascript, for that, you might look into typescript.
For example, you can use try...catch construction:
let route
try {
route = getAddressComponent(addressComponents, 'route').value.long_name
} catch (error) {
route = null
}
As an answer to jeroen:
You can not ?? throw new Error("..."). But you can do:
const throwError = (missingParam) => { throw new Error(`Parameter ${missingParam} is missing`); };
{
someParam: a.anotherParam ?? throwError('anotherParam')
}
When I put a ternary statement or an if statement inside the Object.keys() like bellow:
Object.keys(date).forEach((index) => {
dates[date[index].id] !== undefined ?
dates[date[index].id] =
[...dates[dates[date[index].id], dates[date[index].name]
: null;
});
I get this error from the Linter:
Expected an assignment or function call and instead saw an expression. (no-unused-expressions)
When I use a regular if statement, I get this error,
Parsing error: Unexpected token (Fatal)
Why?
You've duplicated dates in and got some missing brackets in the assignment:
dates[date[index].id] = [...dates[dates[date[index].id], dates[date[index].name]
Which should be:
dates[date[index].id] = [..dates[date[index].id], dates[date[index].name]]
Demo:
Object.keys(date).forEach((index) => dates[date[index].id] !== undefined ?
dates[date[index].id] = [...dates[date[index].id], dates[date[index].name]] : null);
You could use a regular if condition, without a ternary expression, which the linter does not like.
Object.keys(date).forEach((index) => {
if (dates[date[index].id] !== undefined) {
dates[date[index].id] = [
...dates[dates[date[index].id]],
dates[date[index].name]
];
}
});
Basically the tenary is used with an assignment outside of the operator, like
x = a > 4 ? 7: 8;
whereas your assignment takes place inside of the operator.
You just have a few syntax errors in there, probably stemming from the overcomplicated nesting of property accesses. Keep it simple:
for (const index in date) {
const id = date[index].id;
if (dates[id] !== undefined) {
dates[id].push(date[index].name);
// or if you insist:
// dates[id] = [...dates[id], date[index].name];
}
}
Say we have nested ternary statements:
return foo ? 1 : bar ? 2 : 3;
What is the best way to format this code to ensure future readability by others.
This post is the most popular opinion I could find on this. The suggestion there is
return foo ? 1 :
bar ? 2 :
3 ;
return foo ? 1 : (bar ? 2 : 3) ;
To separate function
function getValue(cond1, cond2) {
if(cond1) return 'a';
if(cond2) return 'b';
return 'c';
}
function work() {
const result = getValue(/* some params */);
}
I can't tell if this is accepted or not but i use it this way all the time.
Ternary gives you such a natural testing structure that you can make the code very readable just by making it multiline and indenting properly. I strongly believe that the following usage of ternary is the best manifestation of a nested conditional.
return foo ? 1
: bar ? 2
: 3;
In more complicated cases you can make ternary and comma operator work together beautifully. Keep in mind that the last instruction in a comma separated group gets returned automatically. Super handy for ternary.
return foo ? ( doSometingFoo()
, variable++
, collectResult() // and return foo result
)
: bar ? ( doSomethingBar()
, variable--
, collectAnotherResult() // and return bar result
)
: ( doSomethingReject()
, variable = 0
, rejectSomehow() // and return error code
)
I have a preference for the readability of this style of ternary operator formatting:
return foo
? bar
: baz
? qux
: qiz
? 1
: 2;
For readability just stay away from those statements, they're very easy to misread, if you want something more readable just expand and use normal statments..
Nothing wrong with just having a nested if statement list..
if(foo){
return 1
}else{
if(bar){
return 2;
}else{
return 3;
}
}
Can the javascript shorthand for if-else return out of a function? If so how would this work.
eg.
I have this:
if(boolean){
return;
}
and I would like to write it as this:
(value)? return;
Chrome complains that return is unexpected. Is there anyway to write something like this so that it is valid?
No, you can't do that unless you return a value. For example if your function had to return a value you could have written:
return boolean ? 'foo' : 'bar';
But you cannot stop the execution of the function by returning void using the conditional operator.
If you intend to return from the function at this point in its execution regardless of whether the test evaluates true or false, you can use,
return (value) ? 1 : 2;
But if you merely wish to return early when a test evaluates true (for instance, as a sanity-check to prevent execution when parameters are invalid), the shortest you can make it is:
if (boolean) return;
if(boolean) return;
Single line , readable , perfectly valid;
I know it's an old question but I want to add that there is a non-standard way to return out of a function in shorthand if-else, and that is performing Immediately Invoked Function Expression (IIFE):
function outOfFunction(boolean){
return (boolean)?(()=>{return true;})():(()=>{return false;})();
}
console.log(outOfFunction(true));
console.log(outOfFunction(false));
And if we want to be out of the function or continue with other task:
function shorthandExampleJustTrue(boolean){
var someVar = "I'm out";
return (boolean)?(()=>{return true;})():(()=>{
console.log("here my code ");
console.log(someVar);
return "anythig else";
})();
}
console.log(shorthandExampleJustTrue(true));
console.log(shorthandExampleJustTrue(false));
When we use arrow functions we are able to access to variables out of the immediate function context.
You want to do a ternary operator
which is this:
(bool) ? ifTrue : ifFalse;
Please note: you cannot omit the else portion of a ternary operator.
http://en.wikipedia.org/wiki/Ternary_operation
The conditional "ternary operator" (condition ? expression to evaluate when true : expression to evaluate when false) is often used for simple conditional variable assignment.
if you need :
if( x > 0) {
a = 10;
}else{
a = 30;
}
you can write:
a = (x>0)? 10 : 30;
You can think of it like a simple function, which takes 3 parameters (p1, p2, p3), if p1 is true it returns p2 and if p1 is false then it returns p3.
(p1)? p2 : p3;
And just like such a function, there's no way for it to cause the parent function to return based on the condition. It is not therefore a shorthand for if/else.
if I'm not mistaken you're talking about this right? a short-hand.
return (if the value here is true then ->) && false
example:
const isGood = true && "yeah";
console.log(isGood) //yeah
Use this as your short hand if the value is true then it will return false; using the && operator is better
if(a=="check" && b=some())
The if statement will (in theory) return true if a is equal to "check" and if some() returns something that isn't false/0/null/undefined.
But this throws an error: ReferenceError: Invalid left-hand side in assignment.
In context:
function some(){
return (window.title=="Special")? 0 : window.title;
}
function check(a){
var b;
if(a == 1 && b = some()){
alert("Window's title is: "+b);
}
}
How could I do this without using two if statements? Is it possible?
Group it with ().
if( a=="check" && ( b=some() ) )
http://jsfiddle.net/KsWBq/
This will evaluate the assignment expression, then the result of that expression will be used by the if() statement.