I have been doing some reading lately one article I read was from Opera.
http://dev.opera.com/articles/view/javascript-best-practices/
In that article they write this:
Another common situation in JavaScript
is providing a preset value for a
variable if it is not defined, like
so:
if(v){
var x = v;
} else {
var x = 10;
}
The shortcut notation for this is the
double pipe character:
var x = v || 10;
For some reason, I can't get this to work for me. Is it really possible to check to see if v is defined, if not x = 10?
--Thanks.
Bryan
That Opera article gives a poor description of what is happening.
While it is true that x will get the value of 10 if v is undefined. It is also true that x will be 10 if v has any "falsey" value.
The "falsey" values in javascript are:
0
null
undefined
NaN
"" (empty string)
false
So you can see that there are many cases in which x will be set to 10 besides just undefined.
Here's some documentation detailing the logical operators. (This one is the "logical OR".) It gives several examples of its usage for such an assignment.
Quick example: http://jsfiddle.net/V76W6/
var v = 0;
var x = v || 10;
alert( x ); // alerts 10
Assign v any of the falsey values that I indicated above, and you'll get the same result.
var x = v || 10;
That operator (the "logical" or "short-circuit" OR operator) would normally check the value of v, and if it is a "falsy" value (i.e. it would fail as a condition used in an if statement), 10 becomes the value of x, otherwise v does (and if 10 were a function, it would never be executed).
undefined, null, and 0 are all examples of falsy values that a variable can hold (yes, even the first one), and the operator (or if statement) acts accordingly. In contrast, all objects and arrays (not including null) are "truthy" values, which allows for such things as this (used in the Google Analytics tracker code):
var _gaq = _gaq || []; // Makes a new array _gaq if it is not already there
However, if the referenced variable is not even declared anywhere within the scope chain, then a JavaScript exception will occur.
One way to avoid this is by declaring all your global variables from the start:
var iAmAGlobalVariable; // Holds the value undefined by default
If this is not possible, you should use the typeof operator. It does not attempt to evaluate its operand, and thus an exception will not occur:
var x;
if(typeof v != 'undefined' && v) {
x = v;
} else {
x = 10;
}
Or even better, if you know that the variable would be a global variable, you can treat it as a property of the global (window) object:
var x = window.v || 10;
If v evaluates to false (for example, 0, null, false) then it won't work. You can manually check for undefined:
var x = v !== undefined ? v : 10;
I would use triple equals with ternary in a function for this.
function myTest(x){
return x === undefined ? true: false;
}
Only returns true if x is undefined
See
(http://www.impressivewebs.com/why-use-triple-equals-javascipt/)
and
(http://jsfiddle.net/V76W6/)
I would just use a try-catch
var x = 0;
try
{
x = v;
}
catch(err)
{
x = 10;
}
Here is how to get it working:
var v; //declare v as undefined
// v = 5; //if uncommented x will be 5
var x = v || 10;
alert(x); //output: 10
http://jsfiddle.net/uLLtu/1/
Related
I know that I can test for a JavaScript variable and then define it if it is undefined, but is there not some way of saying
var setVariable = localStorage.getItem('value') || 0;
seems like a much clearer way, and I'm pretty sure I've seen this in other languages.
Yes, it can do that, but strictly speaking that will assign the default value if the retrieved value is falsey, as opposed to truly undefined. It would therefore not only match undefined but also null, false, 0, NaN, "" (but not "0").
If you want to set to default only if the variable is strictly undefined then the safest way is to write:
var x = (typeof x === 'undefined') ? your_default_value : x;
On newer browsers it's actually safe to write:
var x = (x === undefined) ? your_default_value : x;
but be aware that it is possible to subvert this on older browsers where it was permitted to declare a variable named undefined that has a defined value, causing the test to fail.
Logical nullish assignment, ES2020+ solution
New operators are currently being added to the browsers, ??=, ||=, and &&=. This post will focus on ??=.
This checks if left side is undefined or null, short-circuiting if already defined. If not, the right-side is assigned to the left-side variable.
Comparing Methods
// Using ??=
name ??= "Dave"
// Previously, ES2020
name = name ?? "Dave"
// or
if (typeof name === "undefined" || name === null) {
name = true
}
// Before that (not equivalent, but commonly used)
name = name || "Dave" // Now: name ||= "Dave"
Basic Examples
let a // undefined
let b = null
let c = false
a ??= true // true
b ??= true // true
c ??= true // false
Object/Array Examples
let x = ["foo"]
let y = { foo: "fizz" }
x[0] ??= "bar" // "foo"
x[1] ??= "bar" // "bar"
y.foo ??= "buzz" // "fizz"
y.bar ??= "buzz" // "buzz"
x // Array [ "foo", "bar" ]
y // Object { foo: "fizz", bar: "buzz" }
??= Browser Support Oct 2022 - 93%
??= Mozilla Documentation
||= Mozilla Documentation
&&= Mozilla Documentation
The 2018 ES6 answer is:
return Object.is(x, undefined) ? y : x;
If variable x is undefined, return variable y... otherwise if variable x is defined, return variable x.
ES2020 Answer
With the Nullish Coalescing Operator, you can set a default value if value is null or undefined.
const setVariable = localStorage.getItem('value') ?? 0;
However, you should be aware that the nullish coalescing operator does not return the default value for other types of falsy value such as 0 and ''.
However, do take note of the browser support. You may need to use a JavaScript compiler like Babel to convert it into something more backward compatible. If you are using Node.js, it has been supported since version 14.
I needed to "set a variable if undefined" in several places. I created a function using #Alnitak answer. Hopefully it helps someone.
function setDefaultVal(value, defaultValue){
return (value === undefined) ? defaultValue : value;
}
Usage:
hasPoints = setDefaultVal(this.hasPoints, true);
It seems more logical to check typeof instead of undefined? I assume you expect a number as you set the var to 0 when undefined:
var getVariable = localStorage.getItem('value');
var setVariable = (typeof getVariable == 'number') ? getVariable : 0;
In this case if getVariable is not a number (string, object, whatever), setVariable is set to 0
In our days you actually can do your approach with JS:
// Your variable is null
// or '', 0, false, undefined
let x = null;
// Set default value
x = x || 'default value';
console.log(x); // default value
So your example WILL work:
const setVariable = localStorage.getItem('value') || 0;
You can use any of below ways.
let x;
let y = 4;
x || (x = y)
in ES12 or after
let x;
let y = 4;
x ||= y;
If you're a FP (functional programming) fan, Ramda has a neat helper function for this called defaultTo :
usage:
const result = defaultTo(30)(value)
It's more useful when dealing with undefined boolean values:
const result2 = defaultTo(false)(dashboard.someValue)
var setVariable = (typeof localStorage.getItem('value') !== 'undefined' && localStorage.getItem('value')) || 0;
Ran into this scenario today as well where I didn't want zero to be overwritten for several values. We have a file with some common utility methods for scenarios like this. Here's what I added to handle the scenario and be flexible.
function getIfNotSet(value, newValue, overwriteNull, overwriteZero) {
if (typeof (value) === 'undefined') {
return newValue;
} else if (value === null && overwriteNull === true) {
return newValue;
} else if (value === 0 && overwriteZero === true) {
return newValue;
} else {
return value;
}
}
It can then be called with the last two parameters being optional if I want to only set for undefined values or also overwrite null or 0 values. Here's an example of a call to it that will set the ID to -1 if the ID is undefined or null, but wont overwrite a 0 value.
data.ID = Util.getIfNotSet(data.ID, -1, true);
Works even if the default value is a boolean value:
var setVariable = ( (b = 0) => b )( localStorage.getItem('value') );
It seems to me, that for current javascript implementations,
var [result='default']=[possiblyUndefinedValue]
is a nice way to do this (using object deconstruction).
So, I'm working on a game, and I want it so that if any of the variables are "NaN" or undefined, variableThatTriggeredThis will be set to 0.
I didn't try anything so far, I have no ideas how I can fix it.
if(example == NaN || foo == NaN || bar == NaN) {
variableThatTriggeredThis = 0;
}
I also wanted to ask if there's a way to select every variable in the code, or for example multiple variables, just like var(one, two) == "100".
You can check variables directly. NaN or undefined are valued as false.
Then use Logical OR ||
expr1 || expr2 If expr1 can be converted to true, returns expr1; else, returns expr2
Example:
example = example || 0 ;
foo = foo || 0 ;
bar = bar || 0 ;
There are several ways you could write this. Here's one option using array destructuring:
let a = 10;
let b = 0/0; // NaN
let c; // undefined
const undefinedOrNaNCheck = value => (value === undefined || Number.isNaN(value)) ? 0 : value;
[a, b, c] = [a, b, c].map(undefinedOrNaNCheck);
console.log([a, b, c]);
To coerce a variable into a number (defaulting to 0):
example = isNaN(example) ? 0 : example * 1;
To process several variables, one approach is to create a parent object:
const scores = {};
scores.example = 10;
scores.foo = undefined;
scores.bar = 'not a number';
... allowing iteration like this:
Object.keys(scores).forEach(function(key) {
scores[key] = isNaN(scores[key]) ? 0 : scores[key] * 1;
});
Here's a working fiddle.
If you're supporting an older version of javascript (eg. older browsers) you'll need to use "var" instead of "const" and use a "for" loop instead of the "forEach" loop shown above.
I have a variable that gets defined by user input. I want to replace its value only if it's undefined. But not if it's NaN. How can I do it?
I tried doing x || 0 but that also replaces NaN values.
You can do a strict comparison to the undefined value.
if (x === undefined) {
x = 0;
}
Naturally you'll want to be sure that x has been properly declared as usual.
If you have any sensitivities about the undefined value being plagued by really bad code (overwritten with a new value), then you can use the void operator to obtain a guaranteed undefined.You can do a strict comparison to the undefined value.
if (x === void 0) {
x = 0;
}
The operand to void doesn't matter. No matter what you give it, it'll return undefined.
These are all equivalent:
if (x === void undefined) {
x = 0;
}
if (x === void "foobar") {
x = 0;
}
if (x === void x) {
x = 0;
}
Ultimately if someone squashed undefined locally (it can't be squashed globally anymore), it's better to fix that bad code.
If you ever want to check for both null and undefined at the same time, and only those value, you can use == instead of ===.
if (x == null) {
x = 0;
}
Now x will be set to 0 if it was either null or undefined, but not any other value. You can use undefined in the test too. It's exactly the same.
if (x == undefined) {
x = 0;
}
From your question, it seems a little bit like you're specifically looking for number elements, even NaN. If you want to limit it to primitive numbers including NaN, then use typeof for the test.
if (typeof x !== "number") {
x = 0;
}
However, you'll lose numeric strings and other values that can successfully be converted to a number, so it depends on what you ultimately need.
For ES6 users you can simply do:
x ?? 0
?? is a Nullish coalescing operator:
a logical operator that returns its right-hand side operand when its left-hand side operand is null or undefined, and otherwise returns its left-hand side operand.
You can test using typeof (among other things):
if (typeof x == 'undefined') x = y;
Another approach is to test strict equality against undefined:
if (x === void 0) x = y
In this case we use void 0 as a safety since undefined can actually be redefined.
boy. Maybe you could try this,Hello, boy. Maybe you could try this,Hello, boy. Maybe you could try this,Hello, boy. Maybe you could try this,Hello, boy. Maybe you could try this
var a;//undefined
a = ~~a
console.log(a)//0
You can do this quite quickly with just a
x === undefined && (x = 0);
I was pondering something earlier. I wanted to check if a function had already been put into an array. If so throw an exception. I did this little test with the console...
So I guess I could say that the objects are always just references, and after setting a as x I could change x and a would be effected as well?
Would this mean that the condition x = a no matter what, which is what I want.
Using this to check if the function/object is already in the array I could just do this correct...
Is there a better way to do this?
Would this also mean that if I pass a variable to a function and mutate it in that function it will be mutated outside of that function as well?
EDIT
I guess I am right about the mutation with this little test. But I don't get why its bar in the first log in the second example
EDIT END
Example 1:
var x = function(){console.log("hello")}; var a = function(){console.log("hello")};
console.log(x == a); //comes out false
//Set a as x
a = x;
console.log(x == a); //comes out true
Example 2:
Array.prototype.Contains = Array.prototype.Contains || function (obj) {
return this.indexOf(obj) != -1;
};
var x = function(){console.log("hello")}; var a = function(){console.log("hello")};
var z = a;
console.log(x == a); //comes out false
var l = [];
l.push(x);
//Set a as x
a = x;
l.push(a);
console.log(x == a); //comes out true
console.log(l.Contains(x)); //Should come out true
console.log(l.Contains(a)); //Should come out true
console.log(l.Contains(z)); //Should come out false
Your question isn't entirely clear to me but I'll try to answer as best I can.
Improving the function
Your function could be simplified to leverage the indexOf function.
Array.prototype.Contains = Array.prototype.Contains || function (obj) {
return this.indexOf(obj) >= 0;
};
Also I want to point out that in your implementation you're looping through everything when you could exit early by returning inside the if.
Array.prototype.Contains = Array.prototype.Contains || function (obj) {
var i;
for (i = 0; i < this.length; i += 1) {
if (this[i] === obj) {
return true;
}
}
return false;
};
x == a
I think you understand but just want to clarify, x and a are different originally because they are referencing different functions. When you set x = a they are both pointing at the function declared originally in x and are therefore the same. Even thought the functions are identical in terms of implementation, they were both constructed and then placed in different parts of memory.
When you do this:
var x = function(){console.log("hello")}; var a = function(){console.log("hello")}
x and a point to different functions. Even if you compare them for equality, they are not equal as all equality checking does here is see if they point to the same function or not - there is no attempt made to see if they would produce the same output when run or not (that is almost impossible to do in general, after all).
When you do something like x = a, x now references whatever a is referencing - the same object. So now they compare equal.
If you need to see if a function already exists in an array, I suggest instead of just placing arrays in a big list, you create a dictionary (hashmap, hashtable, whatever you want to call it) that uses strings as keys as function as values. The key would be the 'name' of a function - whenever you make that function you'd use the same name, and names in different places in memory but with the same characters in them WILL compare equal.
You're really confused. Everything in JavaScript (except for primitive data types, null and undefined) is an object, and objects are stored in variables as reference. Read the following answer to know more about the differences between the two: https://stackoverflow.com/a/13268731/783743
When you define two identical functions (in your case x and a) JavaScript sees them as separate functions. This is because in addition to the function body a function also maintains its own environment and state. Hence x and a are not the same function which is why x === a returns false.
By setting x = a you're essentially copying the reference stored in a into x. Hence they now point to the same function (which is the function a was originally referring to). The function x was originally referring to is now lost and will eventually be garbage collected. Thus x === a now returns true.
BTW you don't need to create a special Contains function to check whether an object is already inside an array. Just use indexOf:
var array = [];
function x() {}
array.indexOf(x); // returns -1
array.push(x);
array.indexOf(x); // returns 0
If the index is less than 0 the object is not in the array.
If you want to check whether the function body of two functions is the same then use this function:
function sameFunctionBody(a, b) {
return String(a) === String(b);
}
Now console.log(sameFunctionBody(x, a)) will return true as long as both the functions are exactly the same (including whitespace, parameters, function name, etc).
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...