简体   繁体   中英

javascript: define a variable if it doesn't exist

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;)

专业风格:

var SomeVar = SomeVar || 'Default Value';
if (typeof variable === 'undefined') {
    // variable is undefined
    // eg:
    // var variable = "someValue";
}

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.

To actually answer your question of WHY this is happening -- it's only been a little over two years and a month :D -- , 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.

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.

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.

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.

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.

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.

最佳选择:

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

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;

我更喜欢类似 PHP 风格的通用解决方案:

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

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

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 .

You're all very welcome, it's about time I gave back a lil

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM