Are the two identical?
Suppose you have:
var x = true;
And then you have one of either:
x && doSomething();
or
if(x) doSomething();
Is there any differene whatsoever between the two syntaxes? Did I stumble across a nice bit of sugar?
Strictly speaking, they will produce the same results, but if you use the former case as a condition for something else, you will get dissimilar results. This is because in the case of x && doSomething(), doSomething() will return a value to signify its success.
No, they are not identical. While if is a statement, the AND operator is an expression.
That means you could use its result in an other expression, which you can't with an if-statement:
var result = x && doSomething();
Yet, in your case both have the same effect. Use the one that is more readable and represents your program structure better; I'd recommend the if-statement.
Short answer: No.
Long answer:
A stated by #Steve x && doSomething() is an expression,
whereas if(x) doSomething(); is a statement,
As suggested by #Daniel Li and #Bergi, think:
an expression is computed ( supposed to return a value here ).
a statement is declared ( not supposed to return a value here, think side-effects ).
Why is it confusing?
JS allows us to write ( thatExpression );
JS allows us to write thatExpression;
both assuming some kind of doNothingWithValueOf statement.
How to choose?
Do you use:
doSomething() as an
expression , think IsMyObjectWhatever() or MyObjectComputedValue(),
or as a statement, think ModifyMyObject()
And then: Do you use x && doSomething() as an expression ?
You'll end up thinking something like thisStatement( thatExpression ); everywhere, think:
() expression,
; statement.
Then why should I choose?
Obvious is that "It works." doesn´t stand for "It´s right".
If less obvious is when it will make the difference:
just think ()(()())()(); can be right, (;) is wrong.
check #wwaawaw Javascript: difference between a statement and an expression?
or expressions-vs-statements post by Axel Rauschmayer
In a word no, the two statements are not equal, though in the specific circumstances you present the outcome is the same.
x && doSomething(); is an expression, first the x evaluated, because this is an AND and since x is true the second argument (doSomething()) is then evaluated. In this case this means that the method is executed. If x were false then doSomething() would not be executed as the result of the expression cannot be true.
if(x) doSomething(); is a statement. The value of x is checked, and if it is true the scope of the if statement is executed.
I've put together this fiddle to demonstrate (with minor modifications).
Let's play detective.
We'll call our first approach Conditional Arrow Invocation and our second approach Traditional If Else.
We'll create two separate cases in jsperf to evaluate how these two approaches fair.
Conditional Arrow Invocations
const VALUE = true;
const TEST = false;
//test 1
VALUE && !TEST && (() => {
console.log('print me!');
})();
Ops/sec result:
FireFox: 65,152
Chrome: 129,045
Traditional If Else
const VALUE = true;
const TEST = false;
//test 2
if(VALUE && !TEST) {
console.log('print me!');
}
Ops/sec result:
FireFox: 65,967
Chrome: 130,499
Conclusion
As you can see, performance wise there isn't a huge difference but marginally Traditional If Else won over Conditional Arrow Invocation most of the times by an insignificantly small number. This might have something to do with creating an implicit function on the fly.
I also realized Chrome's JavaScript is a lot faster than FireFox's JavaScript execution.
Here is the jsperf link that you can run to evaluate this for yourself.
https://jsperf.com/conditional-methods-vs-traditional-if-else/1
Related
I am new to Javascript and sort of working through the weeds on these ternary operators. I have this small code segment:
const x = MSys.inShip ? 'ship launch' : '';
if (x != '') {send_command(x);}
While this works efficiently enough I am curious as to if it can be rewritten inside of the function call. Something like the following:
send_command(const x = MSys.inShip
? 'ship launch'
: MSys.alert("You aren't in your ship!);
This may not make sense with the current example but it's the best idea I had at the time. Basically, I like the shorthand of the ternary style for easy if/then conditionals but I don't like how it's tied to a variable which must then be called. I'm looking for a way to use that shorthand without having to tie to a variable.
Finally, the purpose of this is to see if you are in the ship and if you are, launch. If you aren't don't do anything at all or just send an alert message.
I am curious as to if it can be rewritten inside of the function call.
Yes, it can. But, if you do it there, then there is no need for a variable. You would be passing the function's argument directly inline.
Having said that, you can't pass that MSys.alert() statement as the "else" value because it will be executed in all cases. You'd have to pass a value there that the function can use as its input argument
send_command(MSys.inShip ? 'ship launch' : 'some other string');
Here's an example:
function foo(x){
console.log(x);
}
// If a random number is even, pass "even". If not, pass "odd"
foo(Math.floor(Math.random() * 10) % 2 === 0 ? "even" : "odd");
An important distinction between your two approaches - The second approach will ALWAYS call send_command() whereas your first approach will conditionally call it.
This distinction will matter depending on your implementation of send_command, but it sounds like you want the behavior of the first approach.
Additionally, You can't declare variables using const in a function call. If you just pass in the ternary operator, you will end up calling send_command with either your string, or undefined (the return of calling alert() ).
However, as an answer to your question, yes you can pass the ternary operator to a function like any other value. The ternary operator is an expression that will return a value.
Technically, you could keep a variable (such as operation) below, which references which method you want to execute, depending upon some conditional. And then you could pass that variable method the variable string it should get.
So, as you can see, it can be done. But look at how much complication was added to the process, rather than just using a simple if else statement.
function test_logic ( inShip ) {
// if they are in their ship, the operation should be the send_command method
// otherwise it should be the window alert
var operation = inShip ? send_command : window.alert;
function send_command ( command ) {
console.log( command );
}
// give the operation the desired string
operation( inShip ? 'ship launch' : "You aren't in your ship!" );
}
console.log( "Not in ship test" );
test_logic( false );
console.log( "In ship test" );
test_logic( true );
In the following recursive function, I expect the function to return "arrived" at the end but instead, it returns undefined. Isn't that when the excution goes in the if block the code should return? Appreciate your comments on this.
function myFun(i){
if(i===0){return ('arrived');}
i = i - 1;
myFun(i);
}
If I change the code as follows then it'll return "arrived" but still don't know why the above doesn't return "arrived".
function myFun(i){
if(i===0){return ('arrived');}
i = i - 1;
return myFun(i);
}
The first function does not return a value because all code paths must return a value. And after the first line, there is no return statement. It only returns a value when called with 0 as parameter.
Recursion is a functional heritage and so writing your program in a functional style will yield the best results.
This means avoiding things like
imperative style statements for, if, switch, etc that do not return a value
mutation or variable reassignments like i = i + 1
const myFun = i =>
i === 0
? "arrived"
: myFun (i - 1)
console.log (myFun (10))
// "arrived"
Notice expressions, unlike statements, evaluate to a value. We made the following changes
function statement function myFun (i) { ... } replaced with a function expression myFun (i) => ...
if statement replaced with ternary expression, eg condition ? ifTrue : ifFalse
variable assignment statement i = i - 1; myFun(i) replaced with expression myFun(i - 1)
Note, the return statement itself is a side effect and has little use in a functional JavaScript program.
Going along with the other answer here, all code paths must return a value! An advantage to writing your program in a functional style means you can't write a function that doesn't return a value, nor can you write a conditional with only one branch.
TL;DR: use functional style and your problem automatically vanishes
I have a syntax question, lets say i have the following function. It received text for spell check and returns the correct text or false in case the text was already spelled correctly.
var spellCheck = function (txt) {
var spelledTxt = spell(txt);
if (spelledTxt =! txt) { //the text had a typo.
return spelledTxt;
}
return false;
}
Now in a different function i want to call this function from an ElseIf statement, and i want to get into that statement only if the text had a typo which was corrected. something like:
if(something){
do something....
}else if(spellCheck(word)){
do something with the spelledTxt that was returned from "spellcheck"
}
Can i just do:
else if(var spelledWord = spellCheck(word))
do something with spelledWord.
I forgot a very important thing: spellCheck(word) is very heavy function and i'd like to avoid calling it if not needed. This mean that only if we arrived to the else if() it will be called, and not sooner.
Any expression is valid inside an if statement, and that includes an assignment expression. The value of an assignment expression is the assigned value.
In your case the return value of the function call is the value of the expression, but the var makes it a statement and not a simple expression.
You need to remove the variable declaration part from the statement and then it's fine.
Alternatively, you could simply do it like this:
else {
var spelledWord = spellCheck(word);
if(spelledWord)
do something with spelledWord
}
You can do that. The assignment operation returns a value, which you could use as a boolean expression.
But you should remember that:
In Javascript var statement is function-scoped.
There is a 'hoist' behavior in Javascript.
As a result of 1,2 and some later code refactoring, you could easily introduce a bug to this code.
Type coercion in Javascript is a bit messy.
Reading code with side effects, where one operation could lead to 2 different logic outcomes simultaneously - is really hard work.
I'd consider using the strict comparison operators at least: if (spelledWord = spellCheck(word) !== '')
And if it's possible, try to memoize (cache) results from calling spellCheck function. In that case, you wouldn't need to combine two operations into one at all.
I don't understand the following if-then-else clause, which I found in a piece of code I'm working on.
if (prefstocking && prefstocking >0) {
...
} else {
...
}
Why does the variable prefstocking appear on both sides of the logical operator &&? I thought using the logical operator && meant using both of them, like this: if (x && y = 1) makes sense to me, meaning "if x equals 1 and y equals 1", but what is the meaning of using the same value twice?
Written in plain English, this test reads:
if prefstocking is truthy and its value is greater than 0
however, because most values are truthy, the former check is unnecessary. Any case which fails the first condition would also fail the second. I see a lot of developers write these kind of checks to be extra-sure, but it tells me that they simply aren't thinking about what they're doing.
The first part if (prefstocking && ...) checks the var prefstocking for false, null, undefined, 0, NaN, and the empty string.
These are all called "falsy" values.
If prefstocking is "falsy" then it isn't greater than zero and doesn't need to check that.
Another answer goes into some detail about truthy v. falsy in javascript.
In this case it makes no difference if the test is if (prefstocking > 0) because that will always evaluate to the same result as the original, but the principal is often useful, especially to avoid dereferencing a null or undefined object.
var obj1 = someFunction('stuff', 9); // assume it returns an object
var obj2 = getNullObj(); // assume it always returns null
// this is OK if an object is always returned from the someFunction(...) call
if (obj1.hasData()) { }
// this causes an error when trying to call the .hasData() method on a null or undefined object
if (obj2.hasData()) { }
But, because the logical and && and the or || operators short-circuit, testing like this is safe:
if (obj2 && obj2.hasData()) { }
If the first part is false (falsy) it won't try to evaluate the second part because the logical truth is already know - the whole statement is false if the first part of an and is false. This means .hasData() will never get called if obj2 is null or undefined.
If an object is defined but does not have a .hasData() function then this will still cause an error. Defending against that could look like
if (obj2 && obj2.hasData && obj2.hasData()) { }
// ...or...
if (obj2 && typeof obj2.hasData === 'function' && obj2.hasData()) { }
Short-circuiting allows you to check and avoid failure cases, but checking every possible failure could make your code unreadable and perform poorly; use your judgment.
Others are correct in pointing out that the way to read this is (prefstocking) && (prefstocking > 0). The first condition checks whether prefstocking is truthy. The second condition makes sure it's greater than 0. Now, as to why bother doing that? Here I disagree with the other answers.
There are situations in programming where we might use redundant conditions in an if then clause because of efficiency. In this situation, mathematically speaking the first condition is redundant. That is, if the second condition is true, then the first condition is also true. However, order matters. An if an interpreter checks the first condition and finds it false, followed by an && (and), then it doesn't need to test further. And it probably won't test the second condition (see comments below: according to ECMAScript standard, it definitely won't test the second condition). This could be useful if it is less computationally expensive to check the first condition, such as first ruling out null cases. The specifics of whether it's actually more efficient are hard to quantify with JavaScript because the internals are often not specified and each JS interpreter works in its own way.
Also, an expression of the form if (x && y == 1) would be interpreted as "if x is truthy and if y equals 1". You have misunderstood the order of operations. Both sides of the && make separate conditions. They don't combine into one condition like the might in English. This expression certainly does not mean "if x and y equal 1". Make sure you have understood that.
I can put a return anywhere such as in a function, in an if block, case block.
How come this doesn't work:
(x == "good") ? (return("works")):"";
UPDATE: I know I can do this:
return (x == "good") ? ("works"):"";
Just want to know why the first case isn't acceptable.
It's because the grammar of a ternary operation is this:
condition ? expr1 : expr2
And a return statement isn't technically considered an expression.
Edit: here's some more info. The above explains it in terms of the grammar of the language, but here's a little bit about the reasoning of why.
I've actually dug into this before, because I've always thought it would be cool to be able to do stuff like:
someFlag && return;
Rather than
if (someFlag) return;
The problem, however, is that expressions always need to evaluate to something. This requirement is at odds with the role of the return statement, however, which along with (optionally) returning a result, also immediately terminates execution of the current function. This termination of the current function is logically inconsistent with the need to evaluate the value of the return statement itself, if it were indeed an expression.
Given that inconsistency, the language authors apparently chose to not allow return statements to act as expressions. Hope I managed to word that in a way that makes sense.
are you trying to do this:
return (x == "good") ? "works":"";
return isn't a function, so return("works") isn't correct.
alternatively you could also do:
var x = "bad";
var y = (x=="good")? "works" : "";
return y;
but this is more verbose. So to answer your question, you can put return anywhere in a function, but anything after it won't be executed. so
function x ()
{
var str = "";
return "I love puppies.";
str = "me too!" //this won't ever execute, because return exits the function.
}
The one exception to this is variable declaration, because variables are automatically declared at the beginning no matter where you put them.
function y (){
return "";
var x;
}
is really:
function y (){
var x;
return "";
}
The return keyword should come first:
return (x == "good") ? "works": "";
The reason is that return x; is a statement. You can't use (return x) as an expression.
All expressions can be used where a statement is expected, but not all statements can be used where an expression is expected.
The return keyword marks the beginning of a statement. It is not an expression, which you could use with the ternary operator.
Based off of this grammar for javascript, The ternary operator is defined as :
OrExpression ? AssignmentExpression : AssignmentExpression
Whereas return is a statement (well, the beginning of one anyways).
In any case messing with control flow in an "expressive" (read: "I want to be clever") form like ternary expressions would not be recommended by anyone I know. an if statement is the same amount of characters:
if(x==good) return x;
(x==good)?(return x)
Because "Almost everything is an expression" hasn't made it into the language yet.
Are you saying if x is "good", then return, otherwise do nothing else? In that case,
if (x == "good") return "works";
does the trick. Furthermore, return is not a function, it is a javascript token, so no parentheses should be used with return.
All the answers that begin with "return" are doing different behavior from what I think the OP intended in his ternary operation. I'm guessing the OP wants
x == "good" ? return "works" : "";
to mean
if(x == "good") {
return works;
}
else {
""; //does nothing because the statement ""; has no side effects
}
It doesn't do this because the format is
statement1 ? statement2 : statement3;
All statements may have side-effects but only the return value (in the case of statement1, just the truthiness of it) are considered by the ternary operator.
Even though the ? : is best read in terms of "if" and "then," when thinking closer to the level of syntax it should be thought of as an expression that factors into side-effects and a return value. If you understand the difference between x++ and ++x, you will be able to understand the ternary operator.
By way of example, here are some illegal statements that are illegal for the same reason.
if( (return 5) == 5) {
//...
}
if (loadUserStats(return userId)) == "FAILED") {
throw error("oops");
}
x = return y++;