72

i feel like im trying to do something super simple, but just being stupid about it.

all i want to do is see if a variable has been set previously, and if it has NOT, set it with a default value....here is a sample:

if(!embed_BackgroundColor) {
    var embed_BackgroundColor;
    embed_BackgroundColor = "#F4F4F4";
}

so, once you stop laughing at my code....WHY is it overwriting the variable no matter what?

please save my nerves;)

16 Answers 16

109

Pro style:

var SomeVar = SomeVar || 'Default Value';
Sign up to request clarification or add additional context in comments.

8 Comments

:\ Does this not reassign SomeVar to itself? Indeed it looks like a "pro" style, but it does - in fact - appear to be somewhat un-optimized (esp. for a for/while loop). I would just stick with an if. However, I could be wrong and the interpreter might recognize that it doesn't need to store a var back into itself.
A word of warning: If SomeVar can be a false-y value, this will fail. Things like '', false, and 0 will trip the || and set the default If you want SomeVar to be able to be 'false-y' values, then use a ternary, like in @Jhuni answer (but with the var keyword like in this one). Also agree with @dylnmc, this results in unnessary reassignment. @Paolo Berantino has what i feel is the 'correct' answer. I personally strongly disagree that "small and compact" is nessarily 'Pro Style'. We don't use punchcards anymore, and js minifiers equalize the rest.
Using this approach I receive Uncaught ReferenceError: my_var is not defined (Chrome -v 48.0)
This is not very verbose. A new programmer would not be able to immediately decode what happens. I would not recommend this.
This the wrong answer and a "pro" would certainly not do this due to the issues mentioned by @Fodagus. Also I suspect it might not work in some JS engines, with certain strict settings or linters since it's assigning a value that potentially does not exist (which could be the issue of @popas). Just use the proper way which is typeof Somevar === 'undefined' to avoid all these problems.
|
85
if (typeof variable === 'undefined') {
    // variable is undefined
    // eg:
    // var variable = "someValue";
}

6 Comments

the problem is that no matter what the // var variable = "someValue" is overwriting the pre-defined value that DID exist
I'm not sure why this is accepted. It seems using the code above (with the var variable = "someValue"; line uncommented results in variable always being equal to "someValue" even if it was already defined.
@Mike if it was already defined, you would not get into the if condition.
@pedz it doesn't matter because the 'var' keyword will make the variable inside the if get redefined even if it never enters the if block. JS doesn't have a "block level scope variable definition".
@xDaizu declaration is hoisted but initialization/assignment is not. AFAIK repeated declaration doesn't have any negative side effects. jsbin.com/bibuneseno/edit?js,console,output
|
57

It would be a good coding practice in this case to use the ternary operator. Also you don't need to have three equal signs when comparing with typeof. This is the most concise solution:

b = typeof(b) == 'undefined' ? 0 : b;

This hopefully will save your hands some time.

5 Comments

Similar to the comment on calmbird's response (below ... maybe), it looks like b is being reassigned to itself when it is defined. That seems like it could be bad-ish (not terrible) in a loop. Again, I don't know how the interpreter will deal with this exactly, but it looks like it will be an unnecessary reassignment.
I thinks must use === instead of ==
Should be accepted answer as it does not do dirty equality checking
Sadly your answer is not entirely true, as double equa sign means the inter[reter will automatically try type conversion. Using a === b will always be faster, as the values are strictly compared, ommiting one step.
Technically correct and also multiple examples of poor style, right down to the single-char variable name and lack of declaration. Just wow.
33

To actually answer your question of WHY this is happening, it is because of variable hoisting.

Basically, there is a phase before executing code in the global scope or inside a function where the code is scanned for all var and function declarations (not to be confused with function expressions, but that's a different story).
All these variable and functions are then declared inside the current scope, and only afterwards does the code actually run.

This happens regardless of their position in the code, with scopes corresponding to function bodies, not blocks of statements. And what makes this even more counter-intuitive, even if you set an initial value to variables in their declarations, they will still remain "empty" until the declaration is reached again in normal execution flow.

So when you write:

if(!embed_BackgroundColor) {
    var embed_BackgroundColor;
    embed_BackgroundColor = "#F4F4F4";
}

what actually happens is this:

  1. Code is scanned for var declarations. embed_BackgroundColor is declared inside this scope, regardless of whether it was already declared or not. Its initial value is undefined.

  2. Execution of the code begins. The if statement is run. The variable is declared, but its value is undefined, so the condition is true. Using typeof wouldn't help you distinguish here between an undeclared and a declared-but-not-yet-set variable. It makes no difference anyway.

  3. The var declaration is reached by normal flow of the code. If you had given the variable an initial value it would have been set now. In this case nothing happens.

  4. embed_BackgroundColor is set to the value "#F4F4F4".

So, bottom-line is: you can use typeof variable == 'undefined' as seen in the other answers, or even plain '!variable' as you were initially using, but don't use var or that will ruin everything.

2 Comments

Is it really in a state of being declared but evaluates as "undefined"? I thought the whole purpose of undefined was for things that are not declared! (ie. not defined). Do you mean null?
@Moss No, it really is undefined. It's the default for uninitialized variables in JS (by uninitialized I mean "without a value assigned to them"). Just try it on Firebug or whatever: typeof blah will evaluate to the string 'undefined'.
14

If it's a global variable, I like doing:

var defineMe = window.defineMe || 'I will define you now';

It's important to use the window namespace since referencing undefined variables will cause very bad errors, but referencing undefined properties will not.

1 Comment

Because the definition var defineMe gets hoisted, I don't think you need to use window. to access defineMe, even if it wasn't defined earlier. However, not that if defineMe is falsey (0, false, "") it will be assigned the default value. To avoid it check typeof defineMe==='undefined' instead
11

I prefer this syntax:

embed_BackgroundColor = embed_BackgroundColor || "#F4F4F4"

Can't get much more simple than that! And it seems to work even if it has been var'd.

1 Comment

ReferenceError: embed_BackgroundColor is not defined Need to define var embed_BackgroundColor first
1

If embed_BackgroundColor is a parameter in a function that didn't get passed, you can set a default with

embed_BackgroundColor ? embedBackgroundColor : embed_BackgroundColor = "#F4F4F4";

Full function example

function colorFunctionThing(embed_BackgroundColor) {
  embed_BackgroundColor ? embed_BackgroundColor : embed_BackgroundColor = "#F4F4F4";
  console.log(embed_BackgroundColor);
};
colorFunctionThing();

Outputs

#F4F4F4

Not exactly what you were looking for but still really good to know.

Comments

1

Best option:

if (typeof someVar === 'undefined') someVar = someValue;

1 Comment

You might explain why this is the best option. In my case I still get an error.
1

As of ES2020 you can now use the nullish coalescing operator ??. This avoids reassigning falsy values to the default value.

var embed_BackgroundColor = embed_BackgroundColor ?? "#F4F4F4"

Note that if you are doing a oneliner like this you need to use var; let and const won't let you do it in one line.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator

Comments

1

As of ES2021 you can use, Logical Assignment Operators that looks like this.

embed_BackgroundColor ||= "#F4F4F4";

This is setup does the same as the following code but is shorter and reduces redundancy.

embed_BackgroundColor = embed_BackgroundColor || "#F4F4F4"

This syntax also works for other logical operators like && and ??.

Comments

1

Cleanest way in 2022 ECMA syntax!

If you want to overwrite "nullish" values (see ref below), assign using let might_exist ||= default or pass value with (might_exist || default). (The parentheses are only there for clarity and to avoid operator precedence problems, delete if you'd rather.)

If you want to keep "nullish" values, assign using let might_exist ??= default or pass value with (might_exist ?? default).

On being nullish: ?? will only overwrite null and undefined, whereas || will also overwrite "nullish" values like '' and 0.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_OR_assignment

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_nullish_assignment

1 Comment

It's confusing to refer to '"nullish" values like '' and 0' when the "nullish" in the "nullish assignment" to which you refer expliclty means only null and undefined not those other false-y values.
0

I think your posted code should work. Unless your original value is 0.

The problem is somewhere else.

I'm guessing you defined 'embed_BackgroundColor' out of the scope of your code. And when you run your code, that variable is undefined with in the scope of your code, and will be assigned the default value.

Here is an example:

var embed_BackgroundColor = "#FF0000";

(function(){
  if(!embed_BackgroundColor) {
    var embed_BackgroundColor;
    embed_BackgroundColor = "#F4F4F4";
  }
  alert(embed_BackgroundColor); // will give you #F4F4F4
})();

alert(embed_BackgroundColor); // will give you #FF0000;

Comments

0

I prefer a general solution in PHP-like style:

function isset(x) { return typeof(x)!='undefined'; }

2 Comments

this won't work. It'll give you a reference error: [x] is not defined.
It works, but you need to remember, that isset(obj.arr[x]) won't work if you don't check first for isset(obj) and then isset(obj.arr).
0

I follow Chris West's blog and saw that he posted a pretty cool way at http://gotochriswest.com/blog/2012/07/02/javascript-define-if-undefined/.

Basically, you have the definition for the define function and then use it like this:

define("embed_BackgroundColor", "#F4F4F4");

The above code will define enbed_BackgroundColor in the global context if it is not already defined. The example that Chris used is a bit more useful and is as follows:

alert("jStuff is " + (typeof jStuff == "undefined" ? "un" : "") + "defined.");

define("jStuff.alert", function(msg) {
  alert(msg);
  return msg;
});

alert("jStuff is " + (typeof jStuff == "undefined" ? "un" : "") + "defined.");

var str = jStuff.alert("Show and save this message.");
  • The first alert statement will display, "jStuff is undefined."
  • The second alert statement will display, "jStuff is defined."
  • The final alert statement will display the specified alert and then that string will be stored in the str variable.

Comments

0

Because your if block will execute if embed_BackgroundColor is false, 0, "", null, undefined, or NaN.

But embed_BackgroundColor should not be overwritten if it has already been assigned to another non-empty string... Or at least, it doesn't on my end.

Perhaps it is a case of conflicting scopes, as Aaron Qian has pointed out.

Comments

-3
if(embed_BackgroundColor == "" || embed_BackgroundColor == 'undefined' || embed_BackgroundColor == null){
}

1 Comment

While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.