What does this condition do in ternary? - javascript

Javascript Ternary Condition
I have javascript with this condition, what is this?
var y = (typeof x !== undefined) ? x || 0 : 1;

This (typeof x !== undefined) ? x || 0 : 1; is going to return always true because the typeof operator will return a string.
That condition should compare a string as follow:
(typeof x !== 'undefined') ? x || 0 : 1;
var x;
var str = typeof x !== 'undefined' ? x || 0 : 1;
console.log(str);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Conditional (ternary) Operator explanation:
+--- When condition is true
|
| +--- When condition is false
| |
| |
v v
typeof x !== 'undefined' ? x || 0 : 1;
^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| +---- The condition should be:
| (x === undefined ? 1 : x || 0)
|
+--- Checks for the type of x
Code refactored
var x = 4;
var str = x === undefined ? 1 : x || 0;
console.log(str);// should return 4
var y;
str = y === undefined ? 1 : y || 0;
console.log(str);// should return 1
y = null;
str = y === undefined ? 1 : y || 0;
console.log(str);// should return 0
y = 5;
str = y === undefined ? 1 : y || 0;
console.log(str);// should return 5
y = 5-"5";
str = y === undefined ? 1 : y || 0;
console.log(str); // should return 0
.as-console-wrapper { max-height: 100% !important; top: 0; }
Docs
Conditional (ternary) Operator
typeof

First, there is an error with the condition:
(typeof x !== undefined)
because you are comparing a type against a value.
typeof always returns a string, while undefined is a value. So, whatever type x is, it will be returned as as string. Even if it's value is undefined, "undefined" (notice the quotes?) will be returned as its type and since the string "undefined" has a typeof === "string", the condition will actually branch into the true section, even when x actually is undefined.
So, it needs to be: (typeof x !== "undefined").
Or, you could test the value of x against the value undefined:
(x !== undefined)
But, you can't mix and match values and types.
Now, assuming we correct that, the next part (the true branch):
x || 0
Simply returns x, as long as it is not "falsy" (that is, any value that would convert to the Boolean false). 0, false, NaN, undefined, "" or null are all falsy. So, if x is not falsy, x is returned. If x is falsy, then 0 is returned. This is a way to provide a default return value in case the first value doesn't exist. But, the logic is a bit off here, because if the code has entered the true branch, it's because x is not undefined, which means it's "truthy". And, if it's truthy, then we can safely just return x. So, it really should just be:
x
Finally, the last part (the false branch)
1
Is what will be returned if the original condition is false. In this case, if x is undefined.
So, the code has flaws in it and really should be:
(typeof x !== "undefined") ? x : 1
EXTRA CREDIT:
In reality, any expression you place into the condition of an if statement is going to be converted to a Boolean for the if to do its job. If all you need to know is if x is not a "falsy" value, then all you need to do is write:
x ? x : 1;
The x will be converted to a Boolean.
If it's true (truthy), then x is returned.
If it's false (falsy), then 1 is returned.
Examples:
function testX(x){
return x ? x : 1;
}
// Truthy:
console.log(testX(10)); // 10
console.log(testX({})); // {}
console.log(testX(true)); // true
console.log(testX("something")); // "something"
// Falsy:
console.log(testX("")); // 1
console.log(testX()); // 1
console.log(testX(4-"Z")); // 1 because 4-"Z" == NaN
console.log(testX(false)); // 1
console.log(testX(0)); // 1
console.log(testX(null)); // 1

The condition
(typeof x !== undefined)
asks if x is not of type undefined. Or, if x is defined. This will include any value or even null.
...? x || 0
If so, the expression evaluates to this. Which is the value of x in most cases or 0 if x is anything evaluated to be boolean false, e.g., null, false, etc.
... : 1;
Otherwise (i.e. case when x is undefined), evaluates to 1.
Typing in Javascript is complicated (in my opinion), sometimes it is not easy to remember what it is when you're comparing mixed type stuff, see https://dorey.github.io/JavaScript-Equality-Table/ for a summary matrix.

Admitting that you have a left-hand operand, it does the same thing as :
var y;
if(typeof x !== undefined) {
if(x)
y = x;
else
y = 0;
}
else
y = 1;

Related

What does var n = (t.currentDevicePixelRatio = e || ("undefined" != typeof window && window.devicePixelRatio) || 1); mean?

var n = (t.currentDevicePixelRatio = e || ("undefined" != typeof window && window.devicePixelRatio) || 1);
Can someone tell me what this means? I know "||" means "OR", and I know that an expression like
n = n || {}
is setting the value of n to an empty object if n is a falsy value. But what happens what you have an equals sign in there? And the second component is even more weird to me.
Let's add some whitespace to make it more readable:
var n = (
t.currentDevicePixelRatio = e
||
(
"undefined" != typeof window
&&
window.devicePixelRatio
)
||
1
);
JavaScript expressions are evaluated left-to-right, parentheses-first. So the evaluation order is:
Copy the value of e into t.currentDevicePixelRatio.
The value of e is then emitted by the assignment = statement.
If that value is falsy, then evaluate the right-hand-side of the ||:
So if e is not null (or undefined or an empty string) then that's that and the value of e is also assigned to n and the expression completes.
Otherwise, if window is defined (i.e. this script is running in a web-browser, as opposed to Node.js) then copy the value of window.devicePixelRatio into t.currentDevicePixelRatio and also into n.
If window.devicePixelRatio is undefined then use 1 for both t.currentDevicePixelRatio and n.
Here is how the individual steps break down to:
var n;
if (e) {
t.currentDevicePixelRatio = e;
n = t.currentDevicePixelRatio;
} else if ("undefined" != typeof window && window.devicePixelRatio) {
t.currentDevicePixelRatio = window.devicePixelRatio;
n = t.currentDevicePixelRatio;
} else {
t.currentDevicePixelRatio = 1;
n = t.currentDevicePixelRatio;
}

That Operator || in console.log() works like || operator?

How it's work for example;
let x;
console.log(x || 2); // 2
if
let x = 4;
console.log(x || 2); // 4
if
let x = 5;
let y = 7;
console.log( y || x || 2);
it's mean that console.log() write first value that is true ?
What you're seeing isn't related to console.log. It's called short circuiting.
When comparing values with ||, it will always return the first truthy value. If no truthy values are present, it will return the last value being compared.
let a = false || true;
let b = false || null || 'b';
let c = undefined || !a || 10;
let d = undefined || false || null; // no truthy values
console.log(a); // true
console.log(b); // 'b'
console.log(c); // 10
console.log(d); // null
let x = 5;
let y = 7;
console.log( y || x || 2); //return 7
expr1 || expr2 Returns expr1 if it can be converted to true; otherwise, returns expr2. Thus, when used with Boolean values, || returns true if either operand is true.
Documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators

What's the difference between a ternary operation and this alternative?

I'd like to know why the following two expressions return the same result i.e. when val_bool is always a boolean [true or false]:
('oninput' in document.documentElement && !val_bool) && 'first result' || 'second result';
and
('oninput' in document.documentElement && !val_bool) ? 'first result' : 'second result';
If you open the console and run the following:
var val_bool = true;
('oninput' in document.documentElement && !val_bool) && 'first result' || 'second result';
second result is output. The same result is output when I make a change to ternary:
var val_bool = true;
('oninput' in document.documentElement && !val_bool) ? 'first result' : 'second result';
I'm not familiar with the mechanism with which the first logical expression resolves its result.
In ternary expression x ? y : z the first part is evaluated as boolean and the appropriate value returns.
In another line of code x && y || z things are different: it's basically 2 expressions instead of 1.
This link is useful here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
We can see, that && and || have left-to-rigth associativity, which means the left part is evaluated first. The following lines are equal:
x && y || z
(x && y) || z
Expression x && y is evaluated first, and x && y || z becomes result(x,y) || z.
Example when results differ while inputs are the same:
const logical = (x, y, z) => x && y || z;
const ternary = (x, y, z) => x ? y : z;
console.log(
logical(1, 0, 1) // 1 && 0 || 1 => 0 || 1 => __ 1 __
)
console.log(
ternary(1, 0, 1) // if (1) then 0; otherwise 1 => __ 0 __ (Boolean(1) === true)
)
Just posting this for posterity.
I found a gem of a quote on an article on Logical Operators. Somewhere under Operators || and &&, one paragraph reads:
The result of a || or && expression is always the underlying value of
one of the operands, not the (possibly coerced) result of the test.
It turns out I've been looking at things from the point of view of the evaluation, as opposed to the underlying value.
So my initial question had the following expression:
('oninput' in document.documentElement && !val_bool) && 'first result' || 'second result';
Let's replace the operands with simple variables:
var a = true;
var b = true;
var c = 'first result';
var d = 'second result';
(a && !b) && c || d;
Firstly, (a && !b) will evaluate to false, because a is true and !b is false and true && false is false.
Secondly, that false result will evaluate with c ((false) && c). Again, we end up with false because c will evaluate to a string (true), and false && true is false.
Finally, the result of false will evaluate with d, only this time the operator is || and the evaluation of false || true is true. However, it's not the evaluation that will be returned, but the underlying value, which is second result.
Of course, things will change when I update the original value of b from true to false. Everything to the left of || evaluates to true, so when you evaluate true || true you get true, but which true is the question. It's the true on the left of ||, because if we evaluated 'a' || 'b', the result would be 'a'.
All tolled, it's not equivalent to the ternary operator in function, but the results for the two specific expression [if the variable types remain the same] should be the identical.

When can != be used instead of !==?

Consider the code snippet below from this AngularJS tutorial:
app.factory('Auth',
function ($firebaseSimpleLogin, FIREBASE_URL, $rootScope) {
var ref = new Firebase(FIREBASE_URL);
var auth = $firebaseSimpleLogin(ref);
var Auth = {
register: function (user) {
return auth.$createUser(user.email, user.password);
},
signedIn: function () {
return auth.user !== null;
},
logout: function () {
auth.$logout();
}
};
$rootScope.signedIn = function () {
return Auth.signedIn();
};
return Auth;
});
I understand the difference between != and !== is the first compares by reference and the second compares by value. Since the comparison here is to null, then why has the developer chosen to use !== instead of !=? Is my understanding correct that both would work here?
== / != operator only compares the value of the variables, not the type
=== / !== operator compares the type and the value of the variables
Some examples:
var varA = 5; // int
var varB = '5'; // string
var varC = 5; // int
if(varA == varB) // true (only value compared)
if(varA === varB) // false: because varB is of type string and varA of type int
if(varA == varC) // true
if(varA === varC) // true: because varA and varC are of the same type and have the same value
I often use "if(x != null)" to check if x is either null or undefined. It's safer than just saying "if(x)" since there are other falsey values besides null and undefined.
Here's an overview table, for your convenience: http://jsfiddle.net/QQcVw/1/
0 "" false null undefined
0 Y Y Y n n
"" Y Y Y n n
false Y Y Y n n
null n n n Y Y
undefined n n n Y Y
As you can see, == considers equal three empty "values" (0, "" and false) and two "non-values" (null and undefined). See javascript standard for the exact algorithm.
In most cases, it's a good idea to avoid == and always stick to ===.

Explain a block of crazy JS code inside Sizzle(the CSS selector engine)

So, here is the function for pre-filtering "CHILD":
function(match){
if ( match[1] === "nth" ) {
// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
// calculate the numbers (first)n+(last) including if they are negative
match[2] = (test[1] + (test[2] || 1)) - 0;
match[3] = test[3] - 0;
}
// TODO: Move to normal caching system
match[0] = done++;
return match;
}
The code is extracted from line 442-458 of sizzle.js.
So, why is the line var test = ..., have the exec inputing a boolean? Or is that really a string?
Can someone explain it by splitting it into a few more lines of code?
The exec method will receive a string, because the Boolean Logical Operators can return an operand, and not necessarily a Boolean result, for example:
The Logical AND operator (&&), will return the value of the second operand if the first is truthy:
true && "foo"; // "foo"
And it will return the value of the first operand if it is by itself falsy:
NaN && "anything"; // NaN
0 && "anything"; // 0
The Logical OR operator (||) will return the value of the second operand, if the first one is falsy:
false || "bar"; // "bar"
And it will return the value of the first operand if it is by itself non-falsy:
"foo" || "anything"; // "foo"
Falsy values are: null, undefined, NaN, 0, zero-length string, and of course false.
Anything else, evaluated in boolean context is truthy (will coerce to true).
So, let's look the expression:
var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
match[2] === "even" && "2n" || // return '2n' if match[2] is 'even'
match[2] === "odd" && "2n+1" || // return '2n+1' if it's 'odd'
!/\D/.test(match[2]) && "0n+" + match[2]|| // return '0n+N' if it's a digit(N)
match[2] // otherwise, return the match[2] value
);

Categories

Resources