IIFE singleton global undefined unless called as window.XYZ = IIFE() - javascript

Why does this function run and not initialize global XYZ with the return value?
"use strict";
XYZ = (function(){
var obj = {'a':1,'b':2,'c':3};
console.log("about to return:");
console.log(obj);
return obj;
})();
console.log(XYZ); // shows undefined
jsfiddle
What seems odd is that the first two console.log return sensible output, and then Chrome throws Uncaught ReferenceError: XYZ is not defined
When using window.XYZ explicitly, this works fine:
"use strict";
window.XYZ = (function(){
var obj = {'a':1,'b':2,'c':3};
console.log("about to return:");
console.log(obj);
return obj;
})();
console.log(XYZ); // shows a:1, b:2, c:3

Either will work if "use strict;" is removed. But don't do that -- keep reading.
Strict mode prevents XYZ = ... from becoming a new global variable.
John Resig explains in his overview of strict mode:
An attempt to assign foo = "bar"; where foo hasn’t been defined will
fail. Previously it would assign the value to the foo property of the
global object (e.g. window.foo), now it just throws an exception. This
is definitely going to catch some annoying bugs.
The code with window.XYZ = IIFE() works in strict mode because here the assignment is to a property of an existing object, window.
Using window.XYZ might be "good enough" for many applications, but you may encounter a platform (such as Meteor) where using window.XYZ "short circuits" dependency management in the package manager. In such a case, strict mode can be enabed inside the IIFE but not at the page level.
To use strict mode with a singleton IIFE assigned to a new global, only turn on strict mode inside the IIFE on its first line.
XYZ = (function() {
"use strict";
var obj = {
'a': 1,
'b': 2,
'c': 3
};
console.log("about to return:");
console.log(obj);
return obj;
})();
console.log(XYZ);
Warning: "use strict;" as the 2nd line does not enable strict mode:
Don't do this:
XYZ = 0;
"use strict";
XYZ = ...
You can test whether strict mode is enabled by looking at this inside a function where this is not explicitly set. When strict mode is true, this will be null when unset, but when strict mode is false, this will be window.
See also: What does "use strict" do in JavaScript, and what is the reasoning behind it?

Related

Chrome: Javascript replaces `undefined` by `window` in "this" context [duplicate]

I'm trying to understand what rule for "this" that "use strict"; modifies in the below case.
After reading (http://unschooled.org/2012/03/understanding-javascript-this/) my best guess is that since the functon isStrictModeOn() is not "attached" to anything, this refers to null. Which is suppose to be a more sensible alternative to Javascript just attaching the this to the global object. Is that the correct interpretation of the change that "use strict" is making in this case?
http://www.novogeek.com/post/ECMAScript-5-Strict-mode-support-in-browsers-What-does-this-mean.aspx
function isStrictMode(){
return !this;
}
//returns false, since 'this' refers to global object and '!this' becomes false
function isStrictModeOn(){
"use strict";
return !this;
}
//returns true, since in strict mode, the keyword 'this' does not refer to global object, unlike traditional JS. So here,'this' is null and '!this' becomes true.
That's almost correct. In strict mode, when a function is invoked without a receiver then this is undefined (not null). A better version of that function would be:
function isStrict() {
"use strict";
return (typeof this) === 'undefined';
}
An inherent problem with functions like that is that "strictness" is determined lexically, like scope, so it's static. A tester function that includes its own "use strict"; isn't very useful; it really only tells you whether the JavaScript runtime understands strict mode. One without its own "use strict"; tells you whether the lexical context in which it's defined is in strict mode. That is:
function isStrict() {
function test() {
return (typeof this) === 'undefined';
}
return test();
}
will tell you, when called, whether a "use strict"; was in effect for the scope at which the function is defined. I guess that could be useful. However, if a reference to that function "leaks" into some other context whose "strictness" differs, it's going to continue to report on its static strictness at the point of its definition.
Personally, I would opt for simply ensuring that my code is definitely in strict mode by invoking "use strict"; at the outermost layer possible. That way there's really no need to check for it.

Javascript Pattern to access the global object [duplicate]

I want to check in a script if a certain other module is already loaded.
if (ModuleName) {
// extend this module
}
But if ModuleName doesn't exist, that throws.
If I knew what the Global Object was I could use that.
if (window.ModuleName) {
// extend this module
}
But since I want my module to work with both browsers and node, rhino, etc., I can't assume window.
As I understand it, this doesn't work in ES 5 with "use strict";
var MyGLOBAL = (function () {return this;}()); // MyGlobal becomes null
This will also fail with a thrown exception
var MyGLOBAL = window || GLOBAL
So it seems like I'm left with
try {
// Extend ModuleName
}
catch(ignore) {
}
None of these cases will pass JSLint.
Am I missing anything?
Well, you can use the typeof operator, and if the identifier doesn't exist in any place of the scope chain, it will not throw a ReferenceError, it will just return "undefined":
if (typeof ModuleName != 'undefined') {
//...
}
Remember also that the this value on Global code, refers to the global object, meaning that if your if statement is on the global context, you can simply check this.ModuleName.
About the (function () { return this; }()); technique, you are right, on strict mode the this value will simply be undefined.
Under strict mode there are two ways to get a reference to the Global object, no matter where you are:
Through the Function constructor:
var global = Function('return this')();
Functions created with the Function constructor don't inherit the strictness of the caller, they are strict only if they start their body with the 'use strict' directive, otherwise they are non-strict.
This method is compatible with any ES3 implementation.
Through an indirect eval call, for example:
"use strict";
var get = eval;
var global = get("this");
The above will work because in ES5, indirect calls to eval, use the global environment as both, the variable environment and lexical environment for the eval code.
See details on Entering Eval Code, Step 1.
But be aware that the last solution will not work on ES3 implementations, because an indirect call to eval on ES3 will use the variable and lexical environments of the caller as the environments for the eval code itself.
And at last, you may find useful to detect if strict mode is supported:
var isStrictSupported = (function () { "use strict"; return !this; })();
Update 2019
With all of today's Webpacks and Broccolis, and Gulps and Grunts, and TypeScripts and AltScripts, and create-react-apps, etc, this is pretty useless, but if you're just working with plain, old, VanillaJS and you want to make it isomorphic, this is probably your best option:
var global
try {
global = Function('return this')();
} catch(e) {
global = window;
}
The Function constructor invocation will work even when using --use_strict in node, as the Function constructor always executes in a global non-strict scope.
If the Function constructor fails, it's because you're in a browser with eval disabled by CSP headers.
Of course, with Deno on the way (the node replacement), they may also disallow the Function constructor, in which case it's back to enumerating objects like global, module, exports, globalThis and window, and then duck-type checking which is the global exhaustively... :-/
Crazy one-line solution (Original):
var global = Function('return this')() || (42, eval)('this');
.
.
.
Works
in every environment (that I tested)
in strict mode
and even in a nested scope
Update 2014-Sept-23
This can now fail if HTTP headers in the latest browsers explicitly forbid eval.
A workaround would be to try / catch the original solution as only browsers are known to run this type of subset of JavaScript.
var global;
try {
global = Function('return this')() || (42, eval)('this');
} catch(e) {
global = window;
}
Example:
---
(function () {
var global = Function('return this')() || (42, eval)('this');
console.log(global);
// es3 context is `global`, es5 is `null`
(function () {
"use strict";
var global = Function('return this')() || (42, eval)('this');
console.log(global);
}());
// es3 and es5 context is 'someNewContext'
(function () {
var global = Function('return this')() || (42, eval)('this');
console.log(global);
}).call('someNewContext');
}());
Tested:
---
* Chrome v12
* Node.JS v0.4.9
* Firefox v5
* MSIE 8
Why:
---
In short: it's some weird quirk. See the comments below (or the post above)
In `strict mode` `this` is never the global, but also in `strict mode` `eval` operates in a separate context in which `this` *is* always the global.
In non-strict mode `this` is the current context. If there is no current context, it assumes the global. An anonymous function has no context and hence in non-strict mode assumes the global.
Sub Rant:
There's a silly misfeature of JavaScript that 99.9% of the time just confuses people called the 'comma operator'.
var a = 0, b = 1;
a = 0, 1; // 1
(a = 0), 1; // 1
a = (0, 1); // 1
a = (42, eval); // eval
a('this'); // the global object
Why just don't simply use this in a global scope as param to a wrapper function, as follows?
(function (global) {
'use strict';
// Code
}(this));
Here you go :)
var globalObject = (function(){return this;})();
This should work from anywhere, for example from within another closure.
Edit - just read your post more carefully and saw the part about ES5 strict mode. Can anyone shed some more light on that? This has been the accepted way to get the the global object for as long as I can remember... I sure hope it doesn't end up getting broken.
Edit 2 - CMS' answer has more info on ES5 strict mode's treatment of this.
I think this is pretty much okay in rhino, node, browser and with jslint (without additional workaround flags) - would this help? Am I missing something?
x = 1;
(function(global){
"use strict";
console.log(global.x);
}(this));
Though I myself tend to use the window object and if I do need headless testing I can use env.js (rhino) or Phantom (node).
ECMAScript will be adding this to its standard soon:
https://github.com/tc39/proposal-global
Until its done, this is what's recommended:
var getGlobal = function () {
// the only reliable means to get the global object is
// `Function('return this')()`
// However, this causes CSP violations in Chrome apps.
if (typeof self !== 'undefined') { return self; }
if (typeof window !== 'undefined') { return window; }
if (typeof global !== 'undefined') { return global; }
throw new Error('unable to locate global object');
};
This is not passing jslint: var Fn = Function, global = Fn('return this')();
Try it yourself: http://www.jslint.com/
this will: var Fn = Function, global = new Fn('return this')();
But effectively those are same thing according to MDN:
Invoking the Function constructor as a function (without using the new operator) has the same effect as invoking it as a constructor.
This following solution works in:
Chrome
Node.JS
Firefox
MSIE
Web Workers
The code is:
(function (__global) {
// __global here points to the global object
})(typeof window !== "undefined" ? window :
typeof WorkerGlobalScope !== "undefined" ? self :
typeof global !== "undefined" ? global :
Function("return this;")());
You just need to change X for the name of the variable that you would like to
I had this problem before, I'm not happy with the solution, but it works and passes JSLint (assume browser|assume node):
"use strict";
var GLOBAL;
try{
/*BROWSER*/
GLOBAL = window;
}catch(e){
/*NODE*/
GLOBAL = global;
}
if(GLOBAL.GLOBAL !== GLOBAL){
throw new Error("library cannot find the global object");
}
once you have the GLOBAL var you can do your checking, and at the end of the script type
delete GLOBAL.GLOBAL;
Here's what I am using:
"use strict";
if(this && this.hasOwnProperty && !this.hasOwnProperty('globalScope')){
try {
globalScope = Function('return this')();
}catch(ex){
if(this.hasOwnProperty('window')){
globalScope = window;
}else{
throw 'globalScope not found';
}
}
}

How to check if variable has been declared, although uninitialized?

How to check if a JavaScript variable has actually been declared?
This solution doesn't work in my case:
JavaScript check if variable exists (is defined/initialized)
Example:
(function(){
var abc;
alert(typeof abc === 'undefined') // true
})();
Same as:
(function(){
alert(typeof abc === 'undefined') // true
})();
It produces true in both cases. I could do this:
(function(){
var abc;
var isDefined = false;
try { isDefined = abc || !abc; }
catch(e) {}
alert(isDefined); // true
})();
It works, but I'm looking for anything better that this, x-browsers.
EDIT: I want to use it in a piece of dynamic code which runs via eval and checks if a certain variable exists in either local or global scope.
This question has been asked many times, the answer is "you can't" (other than using try..catch as in the OP).
You can check for properties of an object using in or hasOwnProperty, however both those require that you can access the object that you wish to test. Variables belong to a variable object (ES 3) or environment record (ES 5) of an execution context, and they aren't accessible so you can't check their properties.
The special case is the global object, because global variables (i.e. properties of the global environment record) are made properties of the global object, so you can do:
var global = this;
var foo;
// Declared but not initialised
foo in global // true
global.hasOwnProperty('foo'); // true
// Not declared or initialised
bar in global // error
global.hasOwnProperty('bar'); // true
However, the hasOwnProperty method is not supported on the global object for versions of IE < 9.
You can detect this using "use strict" like this:
"use strict";
try {
myVar = 7;
console.log("myVar is "+myVar);
} catch(e) {
console.log("error");
}
Run the script and it will print "error". Then comment out the "use strict" and run it again; it will print "myVar is 7".

Object in strict mode

I have an object and I need it to run the content of the page. I need to wrap it with strict mode. I tried to return it to use in global scope, but it didn't solve my issue.
(function($) {
"use strict";
var MyObj = {
// some code here.
}
return MyObj;
})(jQuery);
console.log(MyObj); // <= undefined
How can I access to this object from anywhere of my project?
What you have there is an immediately-invoked function expression (IIFE) which is specifically designed to keep things separate from the external scope. Since you're returning MyObj, all you have to do to make it available in the global scope is this:
var MyObj = (function($) {
"use strict";
var MyObj = {
// some code here.
}
return MyObj;
})(jQuery);
console.log(MyObj);
The other way to do this would be to put MyObj in the global space explicitly. In a browser, the global object is called window, so you could, inside your IIFE, say window.MyObj = { /* some code here */ }. I would discourage this approach, though, because it's not clear to the outside observer that that's happening (i.e., you would have to rely on documentation). The better approach is to return the objects you want to expose, and the caller can choose to put those in global space.
Using use strict, you can only put an Object in int the global namespace explicitly.
For example, you could use window.myObj = MyObj in your function.
Another possible way to achieve your goal is by passing the global object to your function (it could be window in the browser or global in nodejs).
(function($, global) {
"use strict";
var MyObj = {}
global.myObj = MyObj;
})(jQuery, window);
Moreover, as Ethan suggested, since you return MyObj, you could simply assign the result of the invocation to a variable.
var myObj = (function($) {
"use strict";
var MyObj = {}
return x
})(jQuery);
myObj; //now defined in the global scope

Can't create object properties in strict mode

If I use strict mode the following code does not work. It fails on the this.bar = 'foobar'; line. Why is this so? How can I make an object property in strict mode?
<html>
<body>
<script>
"use strict";
var foo = (function () {
this.bar = 'foobar';
return this;
}());
alert(foo.bar);
</script>
</body>
</html>
edit:
Thanks to James Allardice for pointing out the problem.
I was erroneously thinking that the self executing function was creating an object but it isn't. I needed to do one of the following instead:
"use strict";
var foo = new function () {
this.bar = 'foobar';
};
alert(foo.bar);
or (this one JSLint likes better)
"use strict";
var foo = (function () {
var obj = {};
obj.bar = 'foobar';
return obj;
}());
alert(foo.bar);
In strict mode, this will not refer to the window. In your example, removing the strict mode directive will cause this to refer to window.
Since in strict mode, this in your example is undefined, you get an error. That's because you can't set properties on something that is undefined.
From MDN (emphasis on the parts relevant to your situation):
First, the value passed as this to a function in strict mode isn't
boxed into an object. For a normal function, this is always an object:
the provided object if called with an object-valued this; the value,
boxed, if called with a Boolean, string, or number this; or the global
object if called with an undefined or null this...
Automatic boxing is a performance cost, but exposing the global object in browsers is a security hazard, because the global object provides access to functionality "secure" JavaScript environments must restrict. Thus for a strict mode function, the specified this is used unchanged

Categories