optional arguments and default value - javascript

I am new to javascript does the following 2 functions does the same thing and would you pick one over another?
var multiply = function(arg1, arg2) {
arg1 && (arg1 = 0);
arg2 && (arg2 = 0);
return arg1*arg2;
}
var multiply = function(arg1, arg2) {
arg1 = arg1 || 0;
arg2 = arg2 || 0;
return arg1*arg2;
}
the reason i am asking is i saw something like this for the first time
function(path, limit) {
var ref = firebaseRef(path);
limit && (ref = ref.limit(limit)); //if i understood correctly this line does an assignment based on condition without an if statement
return $firebase(ref);
}

function(path, limit) {
var ref = firebaseRef(path);
limit && (ref = ref.limit(limit)); // Important
return $firebase(ref);
}
The Important line, can be written like this
if (limit) {
ref = ref.limit(limit);
}
But if you wanted to write it like the first way, you would have done,
ref = limit && ref.limit(limit)
This has one problem, when limit is Falsy && immediately returns the evaluated Falsy value of limit, so ref is Falsy now. You wouldn't have wanted this, I believe.
At the end of the day, as a programmer, readability and maintainability of the code of the code what we write matters. So, I would recommend using an explicit if check, which I mentioned at the beginning of the answer.
Note: Also, as noted by others, the first multiply should have been like this
var multiply = function(arg1, arg2) {
arg1 || (arg1 = 0);
arg2 || (arg2 = 0);
return arg1 * arg2;
}
Even better, I would have written it like this
var multiply = function(arg1, arg2) {
return (arg1 || 0) * (arg2 || 0);
}

Both are variable assignments which evaluate differently on the logical operation.
For example expr1 && expr2 will return expr1 if expr1 returns false otherwise the variable assignment will evaluate to the second expression (i.e. expr2).
Using the logical-or operation will return expr1 if it evaluates to true, otherwise it will return expr2.
Consider the following:
// Logical AND
var a1 = true && true; // t && t returns true
var a2 = true && false; // t && f returns false
var a3 = false && true; // f && t returns false
var a4 = false && (3 == 4); // f && f returns false
var a5 = "Cat" && "Dog"; // t && t returns Dog
var a6 = false && "Cat"; // f && t returns false
var a7 = "Cat" && false; // t && f returns false
// Logical OR
var o1 = true || true; // t || t returns true
var o2 = false || true; // f || t returns true
var o3 = true || false; // t || f returns true
var o4 = false || (3 == 4); // f || f returns false
var o5 = "Cat" || "Dog"; // t || t returns Cat
var o6 = false || "Cat"; // f || t returns Cat
var o7 = "Cat" || false; // t || f returns Cat
For more information, see: Mozilla Developer Network on Logical Operator Expressions

I think the first one will actually do the opposite of what you want. Let's test this with a few cases:
arg1 && (arg1 = 0);
If arg1 is 0, or any other falsy value, so the execution goes as follows:
0 (meaning false) AND an assignment. The expression will immediately return false without executing the arg1 = 0 statement, because false || (t/f) always returns false.
If arg1 is 1, or any other truthy value, so we have:
1 (meaning true) AND an assignment. The assignment will run this time, because it has to see what the second condition returns. Therefore, arg1 will be set to 0.
The correct snippet is the second.

Related

React Conditional Rendering, avoid 0 evaluated to false/undefined

I have checked the other Q/As. Mine is a bit different and I'm new to ReactJS.
Following code for setting const variable evaluates 0 as false/undefined
and value returned from myFunc is "" :
function formatAmount(x){
if(x === undefined || x === null) return "";
return(x.toLocaleString("en-US",{style: "currency", currency: "USD"}));
}
//When user.bill.amount == 0 this line evaluates it to false!!
const amount = user?.bill?.amount || user?.statement?.amount;
function myFunc(){
return(formatAmount(amount));
}
I tried expanding it with a function and IF conditions but the value returned by myFunc is "$NaN":
const amount = () => {
if(user?.bill?.amount || user?.bill?.amount === 0){
return user?.bill?.amount;
}
if(user?.statement?.amount || user?.statement?.amount === 0){
return user?.statement?.amount;
}
}
Expected:
When user.bill.amount == 0, myFunc should return "$0.00"
Actual:
myFunc returns empty string when user.bill.amount == 0
I think the problem here is 0 is falsy so when using || operator 0 will evaluate to false.
const amount = user?.bill?.amount || user?.statement?.amount;
If your environment supports the nullish operator that would work here.
const amount = user?.bill?.amount ?? user?.statement?.amount;

Javascript Check if three values are equal within tolerance of 2

I want to check if 3 RGB values are basically equal but sometimes the values are 1 or even 2 out either way so it's not so straightforward. So 90,90,90 should be equal as should 90,88,90.
At the minute the best I came up with was something like:
if (r != g && r != b) {
if ((r != b && r != (b - 1))) {
// etc
}
}
Expected output:
91,90,90 = true
93,89,93 = false
91,90,89 = true
You can use every() on the array and check if the absolute difference b/w the each value with minimum(or maximum) is less than 2 or equal to 2
const checkRBG = arr => {
let min = Math.min(...arr);
return arr.every(x => Math.abs(min-x) <=2);
}
const tests = [
[91,90,90],
[93,89,93],
[91,90,89],
[90,88,92]
]
tests.forEach(x => console.log(checkRBG(x)))
Do it right
If you want to do if() statements, do this:
var foo = 1;
var baz = true;
var bar = "Hello";
// Not equals (abstract equality)
if(foo !== 2) {
console.log('Not 2');
}
// Equals (abstract equality)
if(baz == "false") {
console.log('false!');
}
// Equals (strict equality)
if(bar===new String('Hello')) {
console.log('Hello as a new String!');
} /* Not equals (strict equality) */ else if(bar==="Hello") {
console.log('Hello as a string');
}
but not != or =
IN FACT I JUST WANT TO SAY " DON'T USE = BUT USE == OR ===" (Explanation down there)
Explanation
ABSTRACT EQUALITY
== returns true if it has any equality EXCEPT equality of types
e.g...
console.log(1 == "1"); // Output: true
console.log(1 == true); // Output: true
console.log("foo" == new String('foo')); // Output: true
STRICT EQUALITY
=== returns false if it has any inequality (literally ANY inequality)
e.g...
console.log(1 === "1"); // Output: false
console.log(1 === true); // Output: false
console.log("foo" === new String('foo')); // Output: false

make a insert function for bracket.js

I'm a making function that replace null by another word/value.
the var in question :
var saveData = {"teams":[[null,null],[null,null]]}
I find out that the variable is a 2D array and to acces a null I shoud do savedata.teams[0][0] so i made a script that modify the variable.
function add(team, data)
{
var str = team.innerHTML;
var str = str.replace(/<td>/g, "");
var text = str.split("</td>");
var i = 0;
while(data.teams[i][0] != null || data.teams[i][1] != null)
{
i++;
}
if( i == data.teams.length - 1){}
if(data.teams[i][0] == null)
{
data.teams[i][0] = text[1];
}
else if(data.teams[i][0] != null)
{
data.teams[i][1] == text[1];
}
$(function() {
var container = $('.creator')
container.bracket({
init: data,
save: saveFn,
userData: ""})
})
}
the result is wierd. it output :
first use :
{"teams":[["team 1",null],[null,null]]}
seconde use :
{"teams":[["team 1",null],["team 2",null]]}
I don't know why, but I suspect the error may come from the while or the if
data.teams[i][0] != null || data.teams[i][1] != null if any of the two value is not null... it move to next element....
its supposed to be:
while(i < data.teams.length)
{
i++;
}
if(data.teams[i][0] == null)
{
data.teams[i][0] = text[1];
}
if(data.teams[i][0] != null)
{
data.teams[i][1] == text[1];
}
Check more into logical operators here.
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.
Logical OR (||)
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.

Why || {} in parent[currentPart] = parent[currentPart] || {}

What is this javascript syntax?
parent[currentPart] = parent[currentPart] || {};
especially this part || {}
It is taken from this javascript code (at http://elegantcode.com/2011/01/26/basic-javascript-part-8-namespaces/)
// Creates a namespace
function namespace(namespaceString) {
var parts = namespaceString.split('.'),
parent = window,
currentPart = '';
var length = parts.length;
for (var i = 0; i < length; i++) {
currentPart = parts[i];
parent[currentPart] = parent[currentPart] || {};
parent = parent[currentPart];
}
return parent;
}
The || operator in javascript works a little differently than many other languages. In javascript, it evaluates to the first 'truthy' value, allowing a "fallthrough" sort of behavior.
Example:
var a = false;
var b = "asdf";
alert(a || b); //alert box with "asdf" since a was false
var c = true;
var d = "asdf";
var e = false;
alert(c || d || d); //alert box with true. d and e were never evaluated, so "asdf" isn't returned. This is called "short-circuiting" operation.
The && operator works similarly in that it evaluates to the first 'falsey' value or the last 'truthy' value if everything is true:
var a = true;
var b = "asdf";
alert(a && b); //alert box with "asdf"
alert(b && a): //alert box with true
var c = 6;
var d = 0;
alert(c && d); //alert box with 0
alert(d && c); //alert box with 0
In JS, logical operators (e.g. &&, ||) return a value, which, when part of an expression, can be used in an assignment.
Thus in the code below:
var a = false
, b = 'hello'
, c = (function() { return a || b })()
c is assigned the string 'hello', because || returns 'hello' to the return statement, which, in turn, returns it from the function and makes the assignment to c.
The definition of the || operator is:
expr1 || expr2 Returns expr1 if it can be converted to true; otherwise, returns expr2.
If parent[currentPart] does not exist, then the expression evaluates to an empty object ({}) and thus parent[currentPart] is initialized to that empty object. If it does exist, then it is left unchanged (that is, it is assigned to itself). The effect is to guarantee that parent[currentPart] always has a (non-falsy) value.
In the expression a = b || c, a will be set to b if b evaluates to true; otherwise, a will be set to c. This is often used because null and undefined both evaluate to false, so it's shorter than saying something like if (b == null) {a = c} else {a = b}.

Logical OR (||) in JavaScript

A book states following rules for OR:
If the first operand is an object, then the first operand is returned.
If the first operand evaluates to false, then the second operand is returned.
If both operands are objects, then the first operand is returned.
If both operands are null, then null is returned.
If both operands are NaN, then NaN is returned.
If both operands are undefined, then undefined is returned.
However I observed following behavior while coding:
var result18 = (NaNVar || undefinedVar); //undefined
var result19 = (NaNVar || nullVar); //null
var result20 = (undefinedVar || NaNVar); //NaN
var result21 = (undefinedVar || nullVar); //null
var result22 = (nullVar || NaNVar); //NaN
var result23 = (nullVar || undefined); //undefined
How can I justify this behavior for those rules?
This rule is the key:
If the first operand evaluates to false, then the second operand is
returned.
All of your left hand side values evaluate to false, so the right hand side is returned.
Here's a good definition from MDN if it helps you:
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; if both are false, returns false.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Logical_Operators
Sorry for the confusion around the description in the book. I was trying to enumerate edge cases and I see how that could cause some confusion.
You can accurately describe the operation using only two rules: if the first argument is truthy then return the first argument; if the first argument is falsy return the second argument. Your third rule doesn't just apply to this operator, an undeclared variable will always causing her to be thrown when you try to use it. It doesn't matter what you try to use it for (with the exception of typeof and delete, which work fine in undeclared variables).
Your book has chosen a terrible way to describe the logical OR operator.
For example, this rule is far too limiting.
If the first operand is an object, then the first operand is returned.
The operator does not do any sort of type check. It doesn't care if the first or second operand is an "object". It only cares about how they coerce to a boolean.
Take this example.
"foobar" || false
The first operand is a string, not an object, but it will coerce to the boolean true, so the first operand is returned.
Boolean("foobar"); // true
Your book is walking through bullet points as though it was following some sort of specified algorithm. There is no such algorithm. The comparison is strictly based on Boolean coercion.
To put it simply,
it evaluates operands from left to right until one is found that will coerce to true or until it runs out of operands.
the last operand evaluated is returned (uncoerced)
11.11 Binary Logical Operators
Let lref be the result of evaluating LogicalORExpression.
Let lval be GetValue(lref).
If ToBoolean(lval) is true, return lval.
Let rref be the result of evaluating LogicalANDExpression.
Return GetValue(rref).
Yes after observing the results, I concluded two simple rules:
//1: if the first operand evaluates to true then it is returned (here it means actual //value of operand is returned but not the evaluated value that is true)
//following values evaluates to ture: non-empty string, non-zero number and //none of these values- NaN, null, undefined
var result = ("Mahesh" || false) //"Mahesh"
var result = ("Mahesh" || true) //"Mahesh"
var result = ("Mahesh" || undefined) //"Mahesh"
var result = ("Mahesh" || null) //"Mahesh"
var result = ("Mahesh" || NaN) //"Mahesh"
var result = (5 || false) //5
var result = (5 || true) //5
var result = (5 || null) //5
var result = (5 || NaN) //5
var result = (5 || undefined) //5
//2: if first operand evaluates to false then the value of second operand is //returned, again without evaluating it
//following values evaluate to false: empty string (""), number zero (0), null, //NaN, undefined or false)
var result = (false || NaN); //NaN
var result = (false || null); //null
var result = (false || undefined); //undefined
var result = (false || "Mahesh"); //Mahesh
var result = (false || 5); //5
var result = (NaN || false); //false
var result = (NaN || true); //true
var result = (NaN || NaN); //NaN
var result = (NaN || null); //null
var result = (NaN || undefined); //undefined
var result = (NaN || "Mahesh"); //Mahesh
var result = (NaN || 5); //5
var result = (null || false); //false
var result = (null || true); //true
var result = (null || NaN); //NaN
var result = (null || null); //null
var result = (null || undefined); //undefined
var result = (null || "Mahesh"); //Mahesh
var result = (null || 5); //5
var result = (undefined || false); //false
var result = (undefined || true); //true
var result = (undefined || NaN); //NaN
var result = (undefined || null); //null
var result = (undefined || undefined); //undefined
var result = (undefined || "Mahesh"); //Mahesh
var result = (undefined || 5); //5
var result = (0 || false); //false
var result = (0 || true); //true
var result = (0 || NaN); //NaN
var result = (0 || null); //null
var result = (0 || undefined); //undefined
var result = (0 || "Mahesh"); //Mahesh
var result = (0 || 5); //5
var result = ("" || false); //false
var result = ("" || true); //true
var result = ("" || NaN); //NaN
var result = (""|| null); //null
var result = (""|| undefined); //undefined
var result = ("" || "Mahesh"); //Mahesh
var result = ("" || 5); //5
//Note: if the first operand evaluates to false and if the second operand is undeclared
//variable then it will cause an error
var result = (false || undeclaredVar); //error
I think that's all in it in simpler words. Can anyone here confirm if I have got right understanding?
I tried this in IE10, hope things will be consistent across other browsers.

Categories