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;
}
Related
Recently I've discovered that sometimes it is more convenient to
condition && fnWhenTrue()
than
if(condition){
fnWhenTrue()
}
Honestly I've fallen in love with it and started using it wherever it makes sense. However I am unable to do a
condition && return
As return is a statement and not an expression. Is there a way around this or is this just not a valid use case and I should stop.
I am able to achieve similar effect using an inline if like this
if(condition) return
But it's just not the same.
Thanks in advance
No, return is not an expression in JavaScript / ECMAScript at the time of this answer.
If you don't want to write several lines / lengthy code, you can use the short if notation:
if (condition) return;
Which is only 2 characters longer than condition && return;!
Just as a reminder, val = exp1 && exp2 is an expression that is roughly equivalent to:
let val;
if (exp1) {
val = exp2;
} else {
val = exp1;
}
(with some main difference that exp1 is evaluated 2 times in my above example, whereas only once in exp1 && exp2).
Just as something to convince you that is probably intended in JS language design, as you can do:
let someResult;
// later...
someResult = exp1 && exp2;
then what would someResult got as value if you had a return instead of exp1 and exp2?
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();
What is the meaning of && in this JavaScript code?
function doIt(a) {
var b = a.parents(),
c = 1;
return b.each(function() {
jQuery(this).hasClass("free-content") && (c = 0)
}), c
}
normally I would think this would be a logical operator AND, but I can't figure out what it does in this line.
The logical AND operator in this case is used in place of an IF-statement. It will set c to 0 if jQuery(this).hasClass("free-content") returns a truthy value.
It's equivalent to:
if (jQuery(this).hasClass("free-content")) {
c = 0;
}
You wondering what it means is actually the reason I dislike this type of coding and consider it a bad practice. It's hard to read and can create confusion, which in turn can create bugs.
It's also worth noting what logical AND returns, if you want to use the returned value:
(Logical AND) Returns expr1 if it can be converted to false; otherwise, returns expr2. Thus, when used with Boolean values, && returns true if both operands are true; otherwise, returns false.
Here's an example showing, in my opinion, bad code since it's hard to follow:
var foo = bar && baz || qux;
The above code is equivalent to:
var foo;
if (bar && baz) {
foo = baz;
} else {
foo = qux;
}
Summary: Do not use logical operators as a nifty way to replace IF-statements or to save keystrokes. It will most likely come back and bite you or someone else in the ass.
I know there will be people arguing against me on this (usually the same people who doesn't want to use semicolon because ASI), but it's just a really bad idea to write code that only an expert would understand. There's no argument against it.
return b.each(function () {
jQuery(this).hasClass("free-content") && (c = 0)
}), c
b.each loops over all entries in b, and checks whether the current element has the class free-content set. Only if that yields true, the second part of the expression is evaluated – because they are concatenated via &&, and JavaScript stops evaluating such an expression when the first part is false, because then the whole expression can’t become true any more.
So if there is an element with that class, the second part is evaluated – and thereby c is set to the value 0 (because that’s the assignment operator = there, and not a comparison).
And after that each loop is finished, the value of c is returned to the outside – because each() and c are connected via the comma operator , here, which evaluates its operands from left to right and then “returns” the second one.
JavaScript allows a lot of “fancy” coding like this, but as Marcus already said in his answer, that is hard to read, and there is no actual advantage here over, say
b.each(function() {
if(jQuery(this).hasClass("free-content")) {
c = 0;
return false;
}
});
return c;
I added the return false here inside the each loop, because once we found an element with that class, we don’t need to search the rest of them any more – that’s something that the person who came up with the original code forgot to do in all their “fancy-ness” … their loop will continue to iterate over all of b’s elements, not matter if it finds the element it is looking for in the first round already.
Recently I saw a statement that works in javascript on the internet and I wonder what the meaning of a single equal sign (=) in javascript as I mostly use in if statements is.
It is a comparison function which include double equal sign (==)
if(i = 1) {
alert(i);
}
This works, I wondered what would happen when the if statement gets assigned to the value of 1 to the variable i and check the value of i which is the same as:
i = 1
if(i) {
alert(i)
}
But I soon realised that the assignation of a value variable needs to have the keyword var
so I changed the code to:
if(var i = 1) {
alert(i);
}
This time the code doesn't work. Why?
The first part of your analysis is of course correct.
Now, the interesting part might be why your last code if (var ...) { doesn't work.
It doesn't work because
1)
var something
is a statement, not an expression.
2) here's how ECMAScript defines the if statement :
IfStatement :
if ( Expression ) Statement else Statement
if ( Expression ) Statement
You must put an expression in the if clause, not a statement.
More on expressions vs statement in this article.
If you check the console, it says Unexpected token var. You're just not supposed to declare variables in the condition of an if statement.
If you ever do actually mean to make an assignment inside the condition, just declare the variable first, like this:
var i;
if(i = 1){
alert(i);
}
I see that you already know the difference between assignment and comparison, though, which is good :)
Single = is indeed an assignation, if you put it in the if condition it will not compare i against 1 but assign the variable i with the value 1 and then use that value as the condition itself, making i a truthy value. So yes, it is the same as you second example.
Also, in javascript it is better to use === instead of == if you are expecting the items to be the same type :
if (1 == '1') {
alert('this is true'); // where you might actually expect it to be false,
in this case it will work properly if you use triple equals (===).
if (1 === '1') {
alert('this is false'); // which is expected
}
Single = is an assignment operator and will always equate to true in an if statement (assuming it is a non negative value).
Double = ,as in ==, is a comparison and will equate to true only if the values on either side of the operator are equal.
Single "=" means "assign to the left var".
As a return value for the IF, you get the value assigned, and since it is 1, the "true" branch is executed.
However, if you put "var" into the IF, it won't return the assigned value, and I think it won't even work at all.
Mistaking "=" and "==" is a common typo.
Your assertion is correct, in that the code is essentially assigning the value 1 to i and then evaluating the expression's truthiness (1 coeerces to true, so the condition passes).
The last example fails because you can't declare variables inside condition expression.
When you don't explicitly invoke the var keyword, the value will be assigned to any existing variable called i that's available in your scope, or, if none exists, create a property i and assign it to the global object (window), which are all callable without invoking the global object (which is why calling, say location will refer back to window.location — unless you've defined var location in scope).
I stumbled across some javascript syntax that seemed like it should produce a parse error of some kind but doesn't:
if (true, true) {console.log('splendid')} else {console.log('horrid')} // splendid
if (true, false) {console.log('splendid')} else {console.log('horrid')} // horrid
It seems only the last expression affects the logic, though all expressions are executed:
if (console.log('super'), true) {console.log('splendid')} // super splendid
Anyone know why that is valid javascript syntax? Is there any practical use for it?
The comma operator chains multiple expressions together, and the result of the operation is the value of the last operand. The only real use for it is when you need multiple side effects to occur, such as assignment or function calls.
The comma operator evaluates each of its operands (from left to right)
and returns the value of the last operand.
https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/Comma_Operator
https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Expressions_and_Operators#comma_operator
commas in javascript are actually pretty arcane. The coolest use I have seen is this
while(doSomething(), checkIfSomethingHappened());
the most common would be the way var is used in modern js
var foo = 1,
bar = 2;
This is also the same as in most other programming languages where you might have multiple iterators in a loop.
int x,y;
for(x = 0, y = 0; x < 10 || y < 100; x++, y++) {
....
}
I permits to do operations and comparisons in the same context.
Example:
if(a = 2, a > 1) console.log('a is', a)