Why some statements can't be used with boolean operators - javascript

I like to use this style for single line conditional function calls:
debug && console.log('Debug is on');
It's much more terse than it's if counter part.
However some statements dont work, e.g. return and debugger:
error && return null
(value == '43') && debugger;
Why does it not work for the above statements? Instead I use:
if (error) return null;
if (value == '43') debugger;

For the same reason you can't say things like these:
const foo = if (bar) { 5 } else { "hi" };
const baz = try { somethingThatCanFail(); } catch (err) { console.error(err); fallback(); };
Javascript, like a lot of other programming languages, retains the difference between an expression and a statement. You can't use a statement in a place where syntactically an expression is expected.
Expressions evaluate to a value, even if that value is undefined. An invocation of a function is an expression. Even an assignment is an expression. But things like try, return, and if are statements.
In some programming languages (notably most functional languages) everything is an expression and evaluates to a value.

When you use the boolean operator, it has to be an expression, not a statement. Some of those keywords/operators are only valid full statements
Here is a related question to explain more
Why can't we have return in the ternary operator?

Related

How do i get this If/else statement to work correctly?

I'm practicing functions and stumped. The code only produces the if block regardless of prompt. Is this a type conversion thing. What am I missing?
function init() {
function dogAllowed(breed) {
var breed = prompt("what type of dog");
if (breed = "pitbull") {
console.log("dogNotAllowed");
} else {
console.log("dog Allowed");
}
}
dogAllowed();
}
window.onload = init();
In your if statement, you need comparison equals (==) not assignment equals (=). So: if (breed == "pitbull") should work.
The comparison operator in JavaScript is ==, or === for strict equality. = is an assignment operator ("put the value on the right inside the variable on the left), and it happens returns the value that was assigned. Here, that value is "pitbull", so your if (breed = "pitbull") is equivalent to breed = "pitbull" followed by if ("pitbull"). JavaScript evaluates non-empty string as true, so you always enter the first branch of that if.
if (breed === "pitbull") should work, and so should if (breed == "pitbull"). Read more about the difference between the two at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators
Since you are not doing a closure, I would recommend separating the functions and also using a ternary operator. I also think you should properly indent your code because it well help people understand it better.
As the other answers mentioned you are using an assignment operator = when you should be using an equality operator. I recommend to never use == because it does type conversion which can lead to more problems later on. Personally I always use === and do the data type conversion myself rather than leaving it up to javascript because its much less prone to bugs.
You can separate your functions like this:
function init() {
dogAllowed();
}
function dogAllowed (breed) {
var breed = prompt("What breed of dog?");
console.log(breed === "pitbull" ? "Dog not allowed" : "Dog allowed" )
}
window.onload = init();

Javascript inline if statement

I had a bit of a weird result in the javascript console. I was trying to look for an alternative (more readable) version of the ternary operator, just for fun. Typing:
{ if(3===4) {5} else {6} }
Evaluates in my console to 6, but for some reason, I can not assign it to a variable, so running:
let a = { if(3===4) {5} else {6} }
Does not let me store it to the variable directly. So my main question is, if this block is returning something, why can't I assign it?
The fact that blocks (and other statements) return values isn't accessible to your code. Consoles can see the result, and it exists at a language specification level, but not in your code.
Your options are the conditional operator¹ (which is quite readable when you're used to it, but you've said you're looking for alternatives to it) or the if/else assigning to a in both parts:
let a;
if (3 === 4) {
a = 5;
} else {
a = 6;
}
Or you could use an inline function (IIFE):
let a = (() => { if (3 === 4} return 5 else return 6; })();
There is also a proposal being floated for "do expressions", which would look like this:
// Currently a proposal, not implemented in engines yet
let a = do { if (3 === 4) 5; else 6; };
That proposal is at Stage 1 of the process, so it may or may not progress, and if it progresses it could change markedly before doing so.
¹ Although you see "the ternary operator" a lot, the proper name is the conditional operator. It is a ternary operator (an operator accepting three operands), and currently JavaScript's only ternary operator, but that could change someday. :-)
Use ternary operator, because you can't assign if statement:
let a = 3 === 4 ? 5 : 6;
The reason this doesn't work is because if is, as you pointed out, a statement. An assignment requires an expression holding a value to be assigned. A statement doesn't (per se) have a value--it simply performs some side-effect instead.
What you can use if you want to assign a value conditionally is the ternary conditional operator, which is an expression:
let a = (3 === 4 ? 5 : 6)
At this point you're probably wondering, why does the console print a value if a statement merely performs side-effects? This is because statements have a completion value, which for an if statement is the completion value of the corresponding branch, and for an expression statement (which is what the 5 and 6 inside the blocks are), is whatever the expression evaluates to. This is mainly useful for when you want to evaluate an expression in the console and see what it produces, without having to issue a console.log() each time you do.
It's not returning anything. if is not an expression, it's a statement; it has no value.
The point of the ternary operator was to provide a more readable version of this:
let a;
if (condition) {
a = 1;
}
else {
a = 2;
}

Is there an equivalent of Swift's guard statement in JavaScript?

I'm starting to develop web apps but I come from the iOS world.
I was wondering if there was an equivalent of Swift's guard statement in JavaScript?
I love return early pattern.
For those who may not know, guard statement is a "return early if statement", here is a very basic example:
myCondition = trueOrFalse()
guard myCondition
else {print("myCondition is false")
return}
print("myCondition is true")
When inside a function you can return early. No need for an actual guard, you can use an if instead.
f () {
myCondition = trueOrFalse()
// Make sure `myCondition` is `true`
if (!myCondition) return console.log("myCondition is false");
console.log("myCondition is true")
}
PS: I return the log statement just to keep it on one line. console.log simply returns undefined, so your function will return undefined. You can split that statement on multiple lines if you think it looks better that way, or want your function return type to always the same as that might help with optimization (eg: always return an integer, so instead of undefined you could return 0).

Do I need to use an "=" when using the ? : javascript shortcut?

Can someone tell me if this is valid javascript to do this:
if (wf.statusId == Status.Dirty) {
wf.createdDate
? promises.push(self.wordFormUpdateSubmit(wf, key))
: promises.push(self.wordFormAddSubmit(wf, key));
}
Would there be cases where this would not work correctly if createdDate was not defined?
Here's what this replaced:
if (wf.statusId == Status.Dirty) {
if (wf.createdDate) {
var updatePromise = self.wordFormUpdateSubmit(wf, key);
promises.push(updatePromise);
} else {
var addPromise = self.wordFormAddSubmit(wf, key);
promises.push(addPromise);
}
}
Also a related question. Would it be possible to use the same syntax with ? : to replace the need for the if () { } construct ?
Using = with ternary operator is not mandatory unless expr1 and expr2 are returning something and you want to save it in some other variable.
In your case, unless promises.push(self.wordFormAddSubmit(wf, key)) and promises.push(self.wordFormUpdateSubmit(wf, key)) are returning something that you want to save it a variable, there is no need for a =.
if (wf.statusId == Status.Dirty) {
promises.push(self[wf.createdDate ? 'wordFormUpdateSubmit' : 'wordFormAddSubmit'](wf, key));
}
wf.createdDate only true if it is not undefined or have value. so this should work fine.
if (wf.statusId == Status.Dirty) {
wf.createdDate
? promises.push(self.wordFormUpdateSubmit(wf, key))
: promises.push(self.wordFormAddSubmit(wf, key));
}
Regards
Mk
This is an example of a ternary statement, using the conditional (ternary) operator, which by definition replaces an if...else construct.
From MDN:
The conditional (ternary) operator is the only JavaScript operator that takes three operands. This operator is frequently used as a shortcut for the if statement.
[source]
Both of your code samples would work the same way, ie if createdDate was undefined the second expression of your ternary statement would run (the line after the :) just like the else block of your if...else construct would run.
The title question seems somewhat unrelated, in that you would only need to use = if you wanted to save a reference to something. In this case, it does not appear that you do.
As for your follow-up question, plenty of people use ternary statements for small checks and tasks that fit on one or a few lines (I personally don't because I prefer the readability of if...else), however anything even moderately complex can quickly make your code hard to read and understand. But yes, technically, ternary statements can replace if...else blocks.
regarding the second question:
assuming you don't need to save the results in a variable, you can do:
promises.push(wf.createdDate?
self.wordFormUpdateSubmit(wf, key) :
self.wordFormAddSubmit(wf, key);
);
and even this works:
promises.push(
(wf.createdDate? self.wordFormUpdateSubmit:self.wordFormAddSubmit)(wf, key)
);

Difference between if (x) { foo(); } and x ? foo() : 0;

Snippet 1:
if ( x ) {
foo();
}
Snippet 2:
x ? foo() : 0;
What are the differences between those two snippets?
Edit: Corrected the syntax error.
Update: btw, it seems that there is an even shorter notation:
x && foo();
Snippet #2 is an invalid ECMAScript expression since it lacks the required : blah in order to make it a ternary.
EDIT: There isn't really a difference between the two snippets, they both invoke foo if x is truthy. If x is falsy (undefined/false/empty string/0/) then first snippet wouldn't evaluate to anything, latter snippet would evaluate to 0 but that 0 really has no impact on the script.
I think you meant to ask the following
// Why should I use
if (x) {
do();
}
// instead of
x && do();
or
// Why should I use
if (x) {
do();
} else {
dont();
}
//instead of
x ? do() : dont()
As they are written, there is no difference in the output. I don't like using the ternary or the && operator in these cases because of the semantics of using the ternary and &&. A ternary returns a value that you're not using, as does the && expression. Therefore, I'd rather use the way the language intends operators to be used.
However, I love using && for null checks
var val = obj && obj.getValue();
Note that in this case, we are using the return value of the expression
Generally, if is a statement (e.g. you can't assign it to a variable) and the ternary operator ?: is part of an expression (yields a value which can be assigned to variables).
Also, the if block can contain statements while the components of ?: can only contain expressions.
In the example you give, there is no difference, since you don't use the result of the ?:.
Both snippets evaluate foo() only if x is a true value.

Categories