3

I'm writing a Javascript library that I hope to be able to minify with the Closure Compiler's ADVANCED_OPTIMIZATIONS option. The library has maybe two dozen global variables which set lower and upper range limits, string literals, etc.

To make these variable accessible from other source files and to avoid dead code removal, I have to "export" them. See Advanced Compilation and Externs.

Therefore, rather than declare variables with this syntax:

var fooMinValue = 10;

I plan to use this syntax:

 window['fooMinValue'] = 10;

I've tested this and it seems to work fine. My questions are, is there any downside to using this syntax and is it supported in all browsers released since IE 6? (Or should I be using a completely different technique altogether?)

4
  • 1
    In global code, you can use this to access the global object. Also if your names are alphanumerics, you don't need the bracket-notation: this.fooMinValue = 10;. Commented Oct 26, 2012 at 17:35
  • @ŠimeVidas FYI: Closure generates the following warning for this syntax this.fooMinValue = 10; JSC_USED_GLOBAL_THIS: dangerous use of the global this object at line 30 character 0 this.fooMinValue = 10;. Regardless, I can't use this in this case because since the varible is not enclosed in quotes, Closure renames it. Useful (for me) comment, none the less. Commented Oct 26, 2012 at 17:53
  • Hm, I'm not sure what's so dangerous about using the global this... Consider this pattern: (function ( root ){ root['fooMinValue'] = 10; }( this )); So you capture the global object into the root parameter, and then use that parameter to set the global properties. This way, you can still be agnostic about accessing the global object (you don't depend on window). Commented Oct 26, 2012 at 17:59
  • @ŠimeVidas I was checking out the compiler warning and came across this Q Closure-compiler-warning-dangerous-use-of-the-global-this-object. Commented Oct 26, 2012 at 23:40

3 Answers 3

2

Although both are properties of the global object, there is a difference: when you declare the variable with var, its [[Configurable]] internal attribute gets set to false. Therefore, it's not possible to change its attributes with Object.defineProperty (except for [[Value]]). The most notable effect is that such variables cannot be deleted:

​var foo = 'bar';
window['bar'] = 'baz';
console.log(foo); // 'bar'
console.log(bar); // 'baz'
delete foo;       // doesn't work, you can't delete vars
delete bar;       // works, bar is an object property
console.log(foo); // 'bar'
console.log(bar); // ReferenceError

Also, when assigning a variable to a property, you make a COPY of the value instead of referencing the variable. This means external changes to the property don't affect the value of the variable.

(function() {
  var foo = 'bar';
  window['foo2'] = foo; //export foo
  console.log(foo);  // will output 'bar'
  setTimeout(function() { console.log(foo) }, 1000); //will output 'bar'
})();
window['foo2'] = 'baz';
console.log(window['foo2']); // will output 'baz'

The above code will produce the following output:

'bar'
'baz'
'bar'
Sign up to request clarification or add additional context in comments.

9 Comments

"it's created as a property of the global object (not an actual variable)" - those two are not mutually exclusive. Global variables are global properties, too. The set of global properties is a super set o the set of global variables. (Your answer implies that global variables are not global properties.)
@ŠimeVidas That was always confusing to me, but your question helped me clarify. However, I still can't find a way to explain that in simple terms (like one short sentence that would fit this answer).
Also, as it relates to Closure-Compiler, you'll be exporting a copy of the value not a reference to the variable. You'll be able to read the value but external changes won't actually affect the variable value. If this isn't what you intend, you'll need to export these variables as properties on an object. See the @expose annotation for details.
@Karl I don't know how Closure Compiler interprets that sequence, but I can tell you how it is evaluated in the browser. So, var fooMinValue = 10; creates a "fooMinValue" global property. Now, window['fooMinValue'] = fooMinValue; assigns the value of that property to that same property. Therefore, it's a no-op. (It's not necessarily a no-op, since that property could've been a getter/setter, in which case the getter/setter function might have side-effects.)
@Karl Yes - if you create it as a property you will be working with a reference and updates go in both directions. Just make sure you reference it consistently (as a property on the window object and not as a global variable).
|
1

It is the same except that if your script is not running on a browser it is very probable that window will be undefined.

You are welcome!

1 Comment

in which case this['fooMinValue'] = 10 works fine, in general. Or you can pass the global scope into a function like: ~function( window ){ window... }( this );
1

It will work; it's perfectly valid syntax; and it's supported in IE6 and up.

Demo: http://ie6test.it/?url=http://jsbin.com/usafeg/2

Comments

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.