What is the difference between these two conditional statements in Javascript?
function comparisonTest() {
var value = "A value";
var compare1 = 5;
var compare2 = "String";
var compare3 = false;
if (value == compare1 || value == compare2 || value == compare3) console.write("True");
else console.write("False");
}
This works as it should - it returns false because the values don't match. However, when I change the conditional to the following...
function comparisonTest() {
var value = "A value";
var compare1 = 5;
var compare2 = "String";
var compare3 = false;
if (value == compare1 || compare2 || compare3) console.write("True");
else console.write("False");
}
it always returns True. I thought that maybe there would be a shorter way of writing that condition for multiple comparisons (although a loop would function just fine), but this is clearly not a way to approach this.
What is going on behind-the-scenes or, rather, how is it being interpreted so that in the second case it always returns true? None of the values I declared are 1 or true, so that's definitely not the problem.
That's because this:
if (value == compare1 || compare2 || compare3)
is the same as this:
if ((value == compare1) || compare2 || compare3)
And, you will see that compare2is a truthy value which satisfies the || operator. See this MDN article on operator precedence for why the == gets evaluated first which makes your first code block work, but makes your second one evaluate like I've shown.
If you want to compare all of them to value, you have to write it out the longhand way like you did in your first code block where you compare each one separately to value.
You may also want to look into using === more often so then you don't have to worry about possible type conversions making things equal that you never intended to be equal. I have a guideline in my own coding to always used === and !== unless there's an explicit reason to want a type conversion. I believe this saves some accidental bugs. See here for more info.
Here is another option:
function comparisonTest() {
var value = "A value";
var answers = [5, "String", false];
/* IE may requires shim found here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
*/
if (answers.indexOf(value) === -1) {
// False
} else {
// True
}
}
Unfortunately I do not believe there is a short way to write conditionals in JavaScript.
The reason the second example returns true is because when you evaluate compare2 this is a truthy value in JavaScript.
I recommend this post about truthy and falsey values in JavaScript
As an aside you may want to look into the difference between == and === in JavaScript
Related
Optional Parameters
I often have JavaScript functions with optional parameters.
Instead of writing a long check like this:
if(param === null || param === undefined){
param = {};
}
I usually use the following syntax:
function doSomething(optionalParam, optionalCallback, optionalFlag){
optionalParam = optionalParam || {};
optionalParam["xyz"] = "value"; //Won't fail if the user didn't pass a value
optionalCallback = optionalCallback || function(){};
optionalCallback(); //If I need the function on 20 places, I don't have to insert a typeof-check everywhere
optionalFlag = optionalFlag || false;
}
The advantages are clear and I can deal with both undefined and null parameters.
This will, however, not work for optional flags that default to true:
someFlag = someFlag || true; //Will never evaluate to false.
Return values
Here's another example where I use that syntax:
function getValueOfIndex(idx){
return anArray[idx] || null; //Returns null if the index is out of bounds
}
My Question:
How does the || operator work in my use case?
Can I use || for all of these situations?
Is there any reason not to use it?
Are there any other types or values where this syntax will fail?
Edit: I recognised that my last point (difference between null||undefined and undefined||null) should belong to a seperate question, so I removed it.
The general answer is that you can't use
parameter = parameter || default;
if the user should be able to pass an explicit parameter that's falsey, and that should take precedence over the default. In that case you need to test explicitly for undefined:
parameter = typeof parameter == "undefined" ? default : parameter;
If the user should be able to pass an explicit undefined value and have that take precedence (a very perverse thing to do), you'll need to test arguments.length to determine how many arguments were passed, so you can default only the remainder.
Why do the following two expression return different values?
null || undefined //evaluates to undefined
undefined || null //evaluates to null
something || somethingElse is an expression, meaning it will always return a value, either the first truthy value, otherwise the last value at all. For example false || 17 is 17. Both null and undefined are falsy, so in both cases, || will return the last value.
Can I use || for all of these situations?
|| Can sometimes do something you wouldn't expect
function thisIsUnexpected (a) {
a = a || "other value";
reurn a;
}
thisIsUnexpected(); // will return "other value";
// it can fail when you pass in a falsy value
thisIsUnexpected(false); // you would want it to return false, yet it will return "other value"
To get the correct behavior, you'd want to use a ternary expression as follows. This can never fail.
function thisIsExpected (a) {
a = (a === undefined) ? "other value" : a;
reurn a;
}
The logical OR operator can be used as long as the expression used to test for the presence of an argument returns true for all the cases where an argument is supplied.
someFlag = someFlag || true; //Will never evaluate to false.
Your example above doesn't work because I can supply the argument false and the expression used to test for the presence of an argument (in this case simply someFlag) will still evaluate to false, implying that an argument was not specified.
So you would need to modify the code to something like:
someFlag = (typeof someFlag === 'boolean') ? someFlag : true;
I have this:
modalTogglePreview: function ($scope) {
if ($scope.modal.wmdPreview === true) {
$scope.modal.wmdPreview = false;
} else {
$scope.modal.wmdPreview = true;
}
}
Is there some way I could achieve the same but without the if statement ?
$scope.modal.wmdPreview = !$scope.modal.wmdPreview;
The unary ! operator interprets its argument as boolean, and returns the boolean complement. Note that this really isn't exactly the same as your code: yours only works if the variable is exactly true when it's tested. In my experience (for what that's worth), relying on variables used as flags in JavaScript to be real booleans is a little fragile. (There are counter-arguments however, so it's up to you.)
To explain further, the ! operator will interpret the values undefined, null, 0, NaN, false, and the empty string "" as being false. Any other value is true.
Aside from using the not operator as Pointy mentioned (which should be the preferred way), if you find yourself setting a boolean value inside an if...else statement, then you are likely doing something wrong.
The condition is already evaluated to a boolean value. So your if...else statement is equivalent to
$scope.modal.wmdPreview = $scope.modal.wmdPreview !== true;
Have a look at these examples:
var result;
if (cond) {
result = true;
}
else {
result = false;
}
This means, if the condition (cond) is true, set result to true. If cond is false, set result to false. The value we assign to result is exactly the value of cond. Hence the above is equivalent to writing
var result = cond;
Now, sometimes we use conditions that don't evaluate to a boolean. To convert any value to its boolean equivalent, you can apply the not operator twice:
var result = !!cond;
Similar for the other way round:
var result;
if (cond) {
result = false;
}
else {
result = true;
}
If cond is true, assign false to result. If cond is false, assign true to result. This is the same as in your situation. The value we assign to result is the opposite of the value of cond. As Pointy showed, we can use the not operator for this:
var result = !cond;
This works with every condition, but depending on the expression, it can make it harder to read. For example, !(x > 5) is not as obvious as x <= 5. So if you find yourself in such a situation, you can usually flip the comparison operator.
The code below represents the idea I am trying to achieve but when I test it doesn't work, what would be the appropriate way to test if q1 and q2 is equal to true?
function processForm() {
if(q1_valid = true && q2_valid = true){
alert("yes");
} else {
alert("no");
}
}
When you use simple = in javascript (and most C-like languages), what happens is that you assign the variable, then return the result of said assignment.
For instance, take the code a = b = true. This can be split up into a = (b = true). Now, if we only look at the part inside the parenthesis, you'll see that what it does is first set b to true, then return b. Then, outside the parenthesis it sets a to whatever b was (which ofcause is true), and returns the value of a. The value of a has nowhere to go, so it's simply dropped.
Now, if we go back to your if-test, what you end up with is basically this:
Set q1_valid to true.
return true (the value of q1_valid) to the && operator.
true is valid for && so it looks at right hand side.
Set q2_valid to true.
return true to the &&.
&& now has true on both sides. Returns true.
Test always passes. q1_valid and q2_valid will always be true after test is run.
The simple solution is to replace = with either == (equals) or === (type and value equals). Your if-check should look like one of the following:
1.
if(q1_valid == true && q2_valid == true)
2.
if(q1_valid === true && q2_valid === true)
Also, since working with booleans (values that are either true or false), the check for equality to true can be omitted altogheter. Another way to do this is simply like this:
if(q1_valid && q2_valid)
Two issues here:
You need to use two equals signs for comparison ==
The variables don't exist in the function, you would need to pass them as parameters when calling the function
function processForm(q1_valid, q2_valid) {
if(q1_valid == true && q2_valid == true){
alert("yes");
} else {
alert("no");
}
}
In the code below, because s is null d = "test"
but if s = "hello" then d would = "hello".
Is this correct as it works? what is the correct way to use ||
var s = null;
var d = s || "test";
alert(d);
|| is "or" ; and understanding what happens here is a bit trickery
var a=false;
var b=true;
result=a||b
will give "result" true (as b is true). What happens is:
'a' is checked - it is false
'b' is checked AFTERWARDS (as no "true" result has been obtained yet, and ONE "true" result would suffice to make the whole || operator be true) - the value of it will be assigned to the left side
if you had
var a=true;
var b="test";
result=a||b
result will yield true; as no other value needs to be checked by the logic of "||"
with
var a=null;
var b="test";
result=a||b;
a will be checked first - it is null, which converts to "false". b is "test", which is non-null, and converts to "true". so the value of b will be assigned.
And yes, this is a correct way to use || ; the feature you use is also called short-circuit evaluation (as it stops evaluating the boolean expression as early as possible)
This works, but if s evaluates to a 'falsy' value, you'll get your default, which might not be what you intended. A more robust, but wordy idiom is
d = (typeof s === "undefined") ? "test" : s;
Yes it is correct unless s is allowed to be blank or 0 which are also falsy values
var s = null;
var d = s || "test";
var s = 0;
var d = s || "test";
var s = "";
var d = s || "test";
All will result in d being "test"
|| is a logical operator. When s is not null then the condition of (s) is true so d is assigned the value of s, otherwise it is assigned 'test'
|| is the OR operator in javascript
so a||b means a OR b in simple terms
explanation of question you have asked is that id you simply do somethings like these in js you will ultimately get in the else block
if(null)
if(undefined)
so s||"test" will mean which ever is not null or undefined
which in this case is test
yes correct, || symbols just does the job of OR. when the first condition is true its gonna return that one.. else it will move to the next... simple as it is...
I have a piece of code that tests for the existence of a variable, using an if statement like the example below. I need to do one thing if the var is set, a different thing if its not. In a certain test case, the var needed to be set to 0, but that is the same is having an unset var in JS, apparently:
var toMatch;
toMatch = 0;
if (!toMatch) {
document.write("no");
} else {
document.write(toMatch);
}
// html is "no"
jsFiddle
So my problem is, how do I test for a var if its value is legitimately zero. I should point out, that in my function possible values to be passed are 0-40+.
In the past I've used a work around like setting the initial value to a number high enough that it is not likely to be passed to the function but that seems hackey to me. Is there a better way to do it?
var toMatch;
toMatch = 0;
if (toMatch === 0) { // or !== if you're checking for not zero
document.write("no");
} else {
document.write(toMatch);
}
toMatch === 0 will check for zero.
toMatch === undefined will check for undefined
the triple equals are strict comparison operators for this sort of scenario. See this blessed question: Difference between == and === in JavaScript
Instead of
if (toMatch)
use
if (toMatch == null)
You can see if a name is undefined with:
if (typeof bad_name === "undefined") {
Javascript is a bit funny when it comes to values and boolean checks. I suggest reading about Truthy and Falsey in Javascript.
You should use the identity inequality operator !==:
var toMatch;
toMatch = 0;
if (toMatch !== 0) {
document.write("no");
} else {
document.write(toMatch);
}
It is also worth understanding the differences between == and ===.