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
Related
I am working on a javascript file with javascript functions that are not inside a closure. Obviously the function is callable by the console.
I know that adding a closure is best practice. But while tinkering i found that if I add in my file
window.myFunction = {}
the function becomes unavailable through the console.
Is this safe ?
All global variables/functions in Javascript (Browser) are a property of the window object:
var x = "foo";
console.log(window.x); //foo
It's not best practice to pollute the global scope, but it isn't "unsafe" if you control which scripts your page uses. (Although I don't recommend using global variables)
If you do need to have a global variable, consider using a name that you know other script won't use:
(function(window, undefined){
var privateVar = 5;
window.mySite = {
foo: "bar",
func: function(){
return "foo";
}
};
})(window);
console.log(window.mySite.func()); //"foo"
console.log(privateVar) //undefined
Now outside of the IIFE (Immediately-Invoked Function Expression) you can use window.mySite or just mySite, while privateVar won't be accessible.
More info on the window object here
JavaScript normally follows the function scope i.e. variables are accessible only within the function in which they are declared.
One of the ways to break this convention and make the variable accessible outside the function scope is to use the global window object
e.g.
window.myVar = 123;
My question is are there any other ways in JavaScript/jQuery to make the variable accessible outside the function scope?
Not with variable declarations, no. You can obviously declare a variable in an outer scope so that it's accessible to all descendant scopes:
var a; // Available globally
function example() {
a = "hello"; // References a in outer scope
}
If you're not in strict mode you can simply remove the var keyword. This is equivalent to your example:
// a has not been declared in an ancestor scope
function example() {
a = "hello"; // a is now a property of the global object
}
But this is very bad practice. It will throw a reference error if the function runs in strict mode:
function example() {
"use strict";
a = "hello"; // ReferenceError: a is not defined
}
As you wrote, variables are only visible inside the function in which they were defined (unless they are global).
What you can do is assign variables to the function object itself:
function foo() {
foo.myVar = 42;
}
console.log(foo.myVar); // outputs "undefined"
foo();
console.log(foo.myVar); // outputs "42"
But I would advise against it. You should really have a very good reason to do something like this.
You can define them as part of a global object, then add variables later
// Define your global object
var myObj = {};
// Add property (variable) to it
myObj.myVar = 'Hello world';
// Add method to it
myObj.myFunctions = function() {
// Do cool stuff
};
See the link below:
Variable declaration
Also, you can declare it without the var keyword. However, this may not be a good practice as it pollutes the global namespace. (Make sure strict mode is not on).
Edit:
I didn't see the other comments before posting. #JamesAllardice answer is also good.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What advantages does using (function(window, document, undefined) { … })(window, document) confer?
I'm increasingly seeing code like this in libraries I've been using:
(function (window) {
var Foo = function () {
}
window.Foo = Foo;
})(window);
The argument I've seen for doing this is to avoid working in the global scope when creating (pseudo) classes. But, correct me if I'm wrong, I always understood that window IS the global scope. I believe, when you create a global variable, you are really only adding a property to window anyway... Unless this is changing for ES5 strict?
So, basically, what's the point? The only benefit I can see to code organised like this is if you wanted to easily change the namespace of your classes at a later date by passing in an argument other than window.
Infact, strict mode throws an exception if you forget to use var for any variable declaration. But that works even without using an outer closure.
Using this pattern is much more for protecting yourself from the outside javascript world. For instance, some other script overwrites window.undefined or any other variable, you can grab the value within that closure to savely access it from within.
For instance
(function _myApp( win, doc, undef ) {
// app code
}( this, this.document ));
Also, when declaring variables with var, or creating function declarations, those are always stored within the current Activation Object respectively the Lexical Environment Record. That means, without using a Function context, you can easily overwrite methods and variables from some other point, because all of those would get stored in the current Context (which would be the global one)
So:
(function _myApp( win, doc, undef ) {
var myVar = 42;
function myFunc() {
}
}( this, this.document ));
(function _myModule( win, doc, undef ) {
var myVar = 42;
function myFunc() {
}
}( this, this.document ));
This works because of closure and Context, but if you would use the same code, without the Function Context, we would obviously overwrite our myVar and myFunc. This could happen from everywhere, within the same file or in another loaded script.
As evil as global variables are, you need to have atleast one or there's no way to access your script. The code you provided is one way to create that one global variable. I prefer this way:
window.Foo = (function () {
var func = function () {
// ...
};
return {
func: func
};
})();
Your're right, but the difference is that the code inside of the function acts like an automatic init function.
(function (window) {
var Foo = function () {
}
var Bar = 69; // not in global scope
window.Foo = Foo; // in global scope
})(window);
As opposed to
var Foo = function () { // in global scope
}
var Bar = 69; // in global scope
and
var Foo = function () { // in global scope
}
function init () {
var Bar = 69; // not in global scope
}
init();
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
I have some properties in an object that I would like to add to the global namespace. In javascript on the browser I could just add it to the window object like so:
var myObject = {
foo : function() {
alert("hi");
}
// and many more properties
};
for (property in myObject) {
window[property] = myObject[property];
}
// now I can just call foo()
foo();
But since rhino doesn't have the global window object I can't do that. Is there an equivalent object or some other way to accomplish this?
I found a rather brilliant solution at NCZOnline:
function getGlobal(){
return (function(){
return this;
}).call(null);
}
The key to this function is that the this object always points to the global object anytime you are using call() or apply() and pass in null as the first argument. Since a null scope is not valid, the interpreter inserts the global object. The function uses an inner function to assure that the scope is always correct.
Call using:
var glob = getGlobal();
glob will then return [object global] in Rhino.
You could use this, which refers to the global object if the current function is not called as a method of an object.
Here's how I've done it in the past:
// Rhino setup
Context jsContext = Context.enter();
Scriptable globalScope = jsContext.initStandardObjects();
// Define global variable
Object globalVarValue = "my value";
globalScope.put("globalVarName", globalScope, globalVarValue);
You could just define your own window object as a top-level variable:
var window = {};
You can then assign values to it as you please. ("window" probably isn't the best variable name in this situation, though.)
See also: Can I create a 'window' object for javascript running in the Java6 Rhino Script Engine
I've not used rhino but couldn't you just use var?
i.e.
var foo = myObject.foo;
foo();
Edit:
Damn knew there'd be a catch! Miles' suggestion would be the go in that case.