Overwrite variable or check for existance - javascript

I am making a simple script in Javascript, calculating some stuff like minimum, maximum etc. and I was wondering which of the following would be faster, and mostly, why:
var x, y, z;
function test(){
if (x === undefined)
x = Math.min(a, b);
if (y === undefined)
y = a / b;
if (z === undefined)
z = a - b;
return [x, y, z];
}
test(); test(); test();
or
function test() {
return [Math.min(a, b), a / b, a - b]
}
Also, should I create variables the first way (Defining them only when requested) or should I define the variables as soon as possible, e.g. at the start of my function? I am creating a RGB to HSV script, using constant RGB values. The HSV is not nececairly always requested (User desides).

Always define your javascript variables at the top, and use them later like:
'use strict';
var a, b, c;
a = 1;
if (typeof b === 'undefined') {
b = a || c;
}
// b is now 1
It is worth mentioning that if you don't define a variable, it becomes a global when first used (which is very bad).
Defining a variable in a condition (e.g. if) is also a very bad practice.

If you do not want to change the x,y,z values if they already exist then checking for their existance and then over writing would be a better option.
if (x === undefined)
x = Math.min(a, b);
if (y === undefined)
y = a / b;
if (z === undefined)
z = a - b;
Since you are working with RGB ,this is the best practice.
Defining the variable at the start is always considered helpful and it hardly has any impact on the performance.

if the variable is not defined use typeof . The Condition should be like
if(typeof x === 'undefined'){
//do something
}

It is totally depending on context whether you want to overwrite existing value or not. Irrespective of the existence of variable if you want to perform operation then below ways is best.
x = Math.min(a, b);
y = a / b;
z = a - b;
This way it faster because in first way you are just check variable is undefined or not if undefined then perform task. Its best to directly perform task.
hope this helps you.

Related

Variable reassignment with chained booleans or ternary operator [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
To clarify:
This is purely for experimental purposes, to learn the quirks, odds and ends of a new (to me) language. I would of course write it readable if I ever were to share this code with anyone else. :-)
I have a function someFunction(x), and two global variables:
let m = 2;
let e = 5;
Inside the function, I want to check if x == m. If this is true, I'd like to pass m to a side function call (sideFunction(m)), then reassign x to e to complete someFunction.
This does work as expected:
const someFunction = x => {
if (x == m) {
sideFunction(m);
x = e;
}
doOtherStuffWith(x);
}
However, I'd like to shorten it, preferably to one line. This is also to understand more about ternaries and/or boolean chaining.
I have tried these two methods:
// Boolean chaining
const someFunction = x => {
x == m && sideFunction(m) && (function () {x = e})();
doOtherStuffWith(x);
}
This does not work, presumably because the assignment x = e only applies to the x in the local scope of the inner, anonymous function...?
// Ternary operator
const someFunction = x => {
x = (x == m && sideFunction(m)) ? e : x;
doOtherStuffWith(x);
}
This does not work, presumably because sideFunction(m) doesn't actually get called, for some reason...?
How can I fix these to make them work?
Alternatively, are there other, elegant ways to perform this check/call/reassignment without a full multi-line if block?
Thank you very much!
The problem with
x == m && sideFunction(m) && (function () {x = e})();
is that && evaluates left-to-right, and will stop as soon as the first falsey value is found. Unless sideFunction returns something explicitly truthy, the third IIFE:
(function () {x = e})()
will never run, resulting in x never being reassigned.
x is local in that function. If you can get the function to run, it will reassign x as desired.
You could use the comma operator:
x == m && (sideFunction(m), x = e);
Similarly
x = (x == m && sideFunction(m)) ? e : x;
won't work because sideFunction would have to return something truthy for the left side of the conditional to evaluate truthily - otherwise, x will be assigned to x, no change.
All this said - I'd highly recommend not doing any of these. Your first approach is much more readable, and readability is much more important than line conservation.
You could take a compound expression with a comma operator and do not care about the result value of sideFunction.
const fn = x => (x == m && (sideFunction(m), x = e), doOtherStuffWith(x));
The comma operator , can be used to chain expressions and return the last one e.g.,
var x = (1 + 2, 10 + 2, 100 + 2);
x;
//=> 102
We can use it to evaluate sideFunction(m) and return e: (sideFunction(m), e).
Since you always want to execute doOtherStuffWith you only need to work out whether to give it e or the original x:
const someFunction = x => doOtherStuffWith(x == m ? (sideFunction(m), e) : x);

in Javascript, why would you write 'b || (b = a);'?

Digging through the glMatrix-0.9.5.min.js source used in my webGL project and I came across several lines of code like this...
vec3.negate = function (a, b)
{
b || (b = a); // <-- What exactly does this line do?
b[0] = -a[0];
b[1] = -a[1];
b[2] = -a[2];
return b;
};
Not sure what that code is doing or even if it's a bug considering it's a third-party file, but I also know I'm not completely up to speed about JavaScript as a language. (For instance, I just learned about protocols because of this. Odd/interesting concept.)
So is that valid, and if so, what exactly is it doing?
My guess is it's shorthand for the following, saying 'If 'b' isn't set, set it to a'
if(!b)
{
b = a;
}
which can also just be written
if(!b) b = a;
which I'd argue is much more clear. But again, I'm guessing as to what that actually means/does. Could be wrong.
Follow-up:
Are these two if-conditions equal?
if(!b){ ... }
if(b == undefined){ ... }
I'm wondering if there's a complication between 'undefined' and a defined value that's 'null'
a better way to write that would be
b = b || a;
That means:
b = b ? b : a; //or
b = b || a;
This is shorthand for
if (!b) { b = a }
Lets break it down:
To the left of the || it is asserting on the truthiness of b http://james.padolsey.com/javascript/truthy-falsey/
If b is truthy, then the part to the right of the || will not be evaluated. If b is falsey, then b will get assigned the value/reference of a.
It's basically setting the value of b to a if b is undefined via the || operator which can be used as a null-coalescing operator in Javascript.
You could think of it in terms of an if-statement as follows :
if(b == undefined){
b = a;
}
A Matter of Preference
It's ultimately a matter of preference with regards to what makes the most sense, but any of the approaches that you'll find in this discussion are likely valid options :
// Explicitly using undefined in the comparison
if(b == undefined) { b = a }
// Using an if-statement (with a not)
if(!b){ b = a }
// Using a ternary operator
b = b ? || a
Regarding Your Follow-up
Follow-up: Are these two if-conditions equal?
if(!b){ ... }
if(b == undefined){ ... }
I'm wondering if there's a complication
between 'undefined' and a defined value that's 'null'
Yes, there can be differences as seen with an empty string, which would have the following results :
var b = '';
!b // true
b == undefined // false
Differentiating null and undefined values can be tricky and since it's a bit of out the scope of this question, you might consider checking out this related discussion on the topic, which commonly recommends the use of if(b == null) { b = a; } as opposed to checks against undefined.

Shorthand way to check for function parameters

In my code, I have a function that creates a new map given a few parameters. I want to make it so that if no parameters are passed, some default values will be used.
Why won't this work:
function create(a,b,c) {
return new Map(a,b,c || 10,1,10); // create new map using a b c as parameters
// or 10, 1, 10 if none entered.
}
create();
Assume that there is a constructor function 'Map' that would accept and process these parameters.
What can i do besides having an if/else type check?
The shortest way i know under some limitations is to use
<var> = <var> || <defaultvalue>;
So
Return new Map((a = a || 10), (b = b || 1), (c = c || 10));
However this way its hardly readable and you might want to consider moving the assignments before the constructor.
The limitation however is that all falsy values lead to the default being assigned which might be a problem for some numeric values.
You can do it this way:
function create(a, b, c) {
a = typeof a !== 'undefined' ? a : 10;
b = typeof b !== 'undefined' ? b : 1;
c = typeof c !== 'undefined' ? c : 10;
return new Map(a, b, c);
}
Javascript does not offer default function value parametization.

DRY - how to exchange this if-statement into less complex

Let assume that we have those six variables: a,b,c,x,y,z.
Is there a better way to write this if statement which is not so hard-reading?
if (((!a && !x) || a === x) && ((!b && !y) || b === y) && ((!c && !z) || c === z))
Now let those variables be much longer and this code is going to be more complicated and less readable.
One obvious approach is to functionize the code that's repeated:
function checkVars(a, b) {
return !a && !b || a === b;
}
// ...
if (checkVars(a, x) && checkVars(b, y) && checkVars (c, z)) {
// ...
}
As quite correctly mentioned, you should give this function a descriptive name, showing what it really does. Apparently, it checks whether or not given variables are falsy OR whether they are identical, so one obvious choice is falsyOrIdentical. Then your if statement will become really self-commenting:
if (falsyOrIdentical(a, x)
&& falsyOrIdentical(b, y)
&& falsyOrIdentical(c, z)) {
// here goes the code
}
If there's more variables to check, Pavlo's approach (a single function using slice.call(arguments) trick to turn all the vars into an Array, then applying this function until it fails to each element of this Array with every method) is the best. But then again, I really wonder shouldn't all these variables actually be a part of a collection - so you'll be able to go with every right away.
Expanding the function approach. The comparison function could be used as a callback inside array's every() method. To not pass the array as a function argument, I'll use call() on arguments.
function compare() {
return Array.prototype.every.call(arguments, function (e) {
return !e[0] && !e[1] || e[0] === e[1];
});
}
if (compare([a, x], [b, y], [c, z])) {
// Do something
}
You should use boolean variables to easier comparision.
Example:
!a && !x could be converted into something like
var aAndBeIsNotTrue = !a && !x
var bAndYIsNotTrue = !b && !y
And if statement would look like
if(aAndBIsNotTrue || a === x) && (bAndYIsNotTrue || b === y)
I think you get the point. You can also great new methods with readable names and put boolean logic inside those methods. These can be also unit tested nicely.
Clean Code book contains nice examples about using boolean variables to ease up complicated if statements.
Hi We can use if else ladder to solve the problem :
Here i am using a function CheckCondition() with return value as bool.
CheckCondition()
{
if((!a&&!x)||a==x)
{
if((!b&&!y)||b==y)
{
if((!c&&!z)||c==z)
{
return true;
}
else return false;
}
else return false;
}
else return false;
}
The if condition can also be break down into further if else ladder.

argumental reference inconsistency in javascript

I have recently encountered a nasty issue in JS.
Let say we pass a map, an array of objects to a function f.
var o=[{a:0}];
function f(a){
for(var i in a){
if (a.hasOwnProperty(i)){
a[i]=null;
}
}
return a;
};
var outp=f(o);
alert(outp[0]+" === "+o[0]+" : "+(outp[0]===o[0]));
// here we expect loose equality, and equality in type,
//furthermore it should identically equal as well, and we got right!
But, we can not pass total responsibility of an object to a function as argument, same like in functional paradigm o=(function(o){return o})(), because any kind of modification to o is not referenced!
var o=[];
function ff(a){
return (a=undefined);
};
var outp=ff(o);
alert(outp+" === "+o.constructor+" : "+(outp===o));
// here we expect true, but we got false!
Why is the above described reference loss and
presumably different referencce handling in the second use case,
though in both case, functions got the array argument in the 0. position?
Javascript always passes arguments by value, so this won't work:
function foo(x) {
x = 100;
}
y = 5
foo(y)
y == 100 // nope
However this does work:
function foo(x) {
x.bar = 100;
}
y = {}
foo(y)
y.bar == 100 // yes
In the second snippet x is still passed by value, but this very value is a reference (pointer) to an object. So it's possible in a function to dereference it and access what's "inside" the object.

Categories

Resources