Is there any way to define within closure a global function? I would like to define one global function so I can call it with onclick event.
(function(){
var private = 'private msg';
function myprivate() {
alert(private)
}
function wanttobeglobal() {
alert(global)
}
})();
Is there any way?
Very bad practice, but the only way short of declaring the variable outside the initial closure is to implicitly create a global variable.
wanttobeglobal = function() {
alert(global);
};
The better way, if you can modify code outside of the closure, is with var:
var wanttobeglobal;
(function() {
// ...
wanttobeglobal = function() {
alert(global);
};
})();
Assign the function to window:
(function(){
var private = 'private msg';
function myprivate() {
alert(private)
}
window.wanttobeglobal = function wanttobeglobal() {
alert(global)
}
})();
Related
Let us consider the workable code:
var storage = {};
(function() {
function internalMethod1() { ...; return; }
function internalMethod2() { ...; return; }
storage.storedMethod = internalMethod1;
})();
storage.storedMethod();
Is there any way to call internalMethod2, if it is not called in internalMethod1? In other words, can I access an anonymous closure from outside, if I have access only to one of its functions?
can I access an anonymous closure from outside?
No. Scopes are private in JS, and there's absolutely no way to access them from the outside (unless you use the engine's implementation-specific debugging API…).
Variables (including functions) are only available in the same scope and its children. If you want to access their values outside of the scope, you're at the mercy of the function to expose them in some way (return, assign to global storage variable etc).
No, you cannot access a private, unreferenced scope after it has been executed. You would need to create another closure to create a reference to whatever private method you wanted to expose.
var storage = {};
(function() {
function internalMethod1() {
return {
internalPublic1: internalMethod2
};
}
function internalMethod2() {
console.log('hi');
}
storage.storedMethod = internalMethod1;
})();
var a = storage.storedMethod();
a.internalPublic1(); //'hi'
Try defining IIFE as variable , return reference to internalMethod2 from IIFE
var storage = {};
var method2 = (function() {
function internalMethod1() { console.log(1) };
function internalMethod2() { console.log(2) };
storage.storedMethod = internalMethod1;
return internalMethod2
})();
storage.storedMethod();
method2();
(function(){
var someValue = 5;
function myFunction(input) = {
return someValue * input;
};
})();
I have a self-executing function, that contains many things, among them at function that I would like to make global. I would typically just declare it in the global scope, but it needs to be able to reference variables that are local only to the self-executing function.
What is the best approach to making the function globally-accessible without getting rid of the self-executing function altogether (thus littering the global space with variables)?
You can add the function to the global window object.
(function(){
var someValue = 5;
window.myFunction = function (input) {
return someValue * input;
};
})();
After the immediate function executed, you can call myFunction().
Alternatively, you could do something like this, which has essentially the same result that ntalbs proposed.
var myFunction;
(function(){
var someValue = 5;
myFunction = function (input) {
return someValue * input;
};
})();
console.log( myFunction( 4 ), window.myFunction ); // output: 20, function(input){return someValue * input}
I'm using jQuery and have a function wrapped inside an immediately-invoked function expression like so:
<script type="text/javascript" src="jquery-1.8.3.min.js"></script>
<script type="text/javascript">
(function ($) {
var message = 'x called';
function x() {
alert(message);
}
})(jQuery);
x();
</script>
This will result is an error since the function "x" is not defined outside the immediately-invoked function expression. Is there any way to call the function "x" outside the immediately-invoked function expression?
Only if you expose the function in some way. For example, you can return it from the outer function:
var x = (function ($) {
var message = 'x called';
function x() {
alert(message);
}
return x;
})(jQuery);
x();
Or, similarly, you can return it on an object:
var obj = (function ($) {
var message = 'x called';
function x() {
alert(message);
}
return {"x": x};
})(jQuery);
obj.x();
Functions and variables declared inside of a function are not directly reachable from outside of that function, unless you provide some means of accessing them by returning something, or giving a reference to a variable declared outside of that function.
Make a namespace for other classes or functions you might want to do this with. You don't want to continually pollute the global namespace but there's no reason you can't make one namespace that's global and put your individual things underneath that:
(function($){
window.MyNamespace = function(){};
var message = "Something here";
$.extend(MyNamespace, {
x: function(){
alert(message);
}
});
})(jQuery)
MyNamespace.x()
You can change your code as follows:
<script type="text/javascript" src="jquery-1.8.3.min.js"></script>
<script type="text/javascript">
var x;
(function ($) {
var message = 'x called';
x = function () {
alert(message);
}
})(jQuery);
x();
</script>
jsFiddle link for this: http://jsfiddle.net/aLnbn/
Yes, ( one way is to: )just return it from the IIFE using a return statement, also you need to "catch" the return by assigning a variable to the IIFE
var foo = (function(){
return your_function;
}());
You can access your method by using your IIFE to return (or augment) a global variable.
You might do it like this:
var globalObject = (function (theObject, $) {
if (theObject.theMethod) {
return theObject;
}
var message = 'theMethod called';
theObject.theMethod = function () {
alert(message);
};
return theObject;
})(globalObject || {}, jQuery);
globalObject.theMethod();
The pattern we use is slightly better.
We have one global object (ie namespace) and we add modules to it by importing js files that contain IIFE's.
Each IIFE adds a new module to a single global object.
This makes it so our entire project has only one global object that can optionally utilize any of our modules by including a file.
I recommend checking out this article, which is a good discussion on the JavaScript module pattern:
http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth
Try this:
var miFunc = (function($) {
var message = 'x called';
function x() {
console.log(message);
}
this.x = x;
return this;
})(jQuery);
miFunc.x();
Test: http://jsbin.com/erucix/2/edit
One of the purposes of a closure is to limit scope. That is why x() is defined and can be called inside of your immediately-invoked function expression but is undefined outside.
To have your code work without refactoring, you can take advantage of JS grammar which differentiates between a function statement and a function operator. Both are semantically identical but the latter can be assigned to a variable which works just right for your scenario:
var x; //scoped *outside* of the closure
(function ($) {
var message = 'x called';
x = function() {
alert(message);
}
})(jQuery);
x(); //alerts 'x called'
You can access your method by using your IIFE to return a global variable.
//IIFEs - Immediately Invoked Function Expressions
var namespaceTestIIFE = (function ($) {
/** Public functions and state. */
var pub = {};
$(document).ready(function () {
//your on ready logic
});
pub.testAlert = function () {
alert('Hello TestAlert');
}
return pub;
})(jQuery);
OR
var compareForm = (function ()
{
/** Public functions and state. */
var pub = {};
pub.testAlert = function () {
alert('Hello TestAlert');
}
return pub;
}());
To access function use "namespace.functionname" for example -
namespaceTestIIFE.testAlert();
I've wrapped all my functions around an immediately-invoked function expression as shown:
(function(){
"use strict";
function toggleComment(parentCommentID) {
$("form#" + parentCommentID).toggle();
}
function scrollBottom() {
window.scrollTo(0, document.body.scrollHeight);
}
})();
However, upon calling one of these functions through a link:
Reply
The Chrome console outputs Uncaught ReferenceError: toggleComment is not defined. Am I mistaken in thinking that an immediately-invoked function expression, as its name suggests, should be invoked immediately and therefore toggleComment should be called? Should I call the function differently?
The function toggleComment is not visible. It's enclosed in the ready function you're using; if you want to be able to call it like that (which is not recommended, in most cases), you have to hoist it outside of that function and make it globally accessible.
And this has nothing to do with strict. If you remove the strict line, this problem will still be the same.
The functions are no longer declared in the global scope. Try
window.toggleComment = function(parentCommentID) {
$("form#" + parentCommentID).toggle();
};
You have declared the functions inside a closure. They're outside of the scope of the HTML tag.
You could set an id to your <a> tag as well as publish your function to the global scope, so you can do this:
(function(){
"use strict";
var toggleComment = function(parentCommentID) {
$("form#" + parentCommentID).toggle();
}
function scrollBottom() {
window.scrollTo(0, document.body.scrollHeight);
}
document.getElementById("yourATagId").onclick(function() {
toggleComment(159);
});
window.toggleComment = toggleComment;
})();
Maybe you could benefit from this simple singleton pattern:
(function() {
var controller = {};
controller = new function() {
this.sampleProperty = "my property";
}
controller.yourFunction = function() {
var localVariable;
console.log("I can access " + this.property);
};
window.controller = controller;
})();
This way, controller will be known to your global scope.
I know how to access the below member function when it's written like this:
var blady_blah=
{
some_member_function: function ()
{
}
}
I access it from outside doing blady_blah.some_member_function()
But how do I access the member function when it's written like this:
(function() {
some_member_function: function ()
{
}
})();
Braces, { }, are used to define both object literals and function bodies. The difference is:
var name = {}; // Object literal
Which you may also see written as
var name = {
};
That's just the same but with some space in between so it's still an object literal, and unfortunately it looks very similar to:
var name = function () { // Function body
};
An object can have members:
var name = {
member: "string"
};
Whereas a function cannot; a function has statements:
var name = function () {
do_something();
var result = do_something_else();
};
You can't write
var name = function () {
member: "string"
};
Because you've mixed the two uses of { } together.
A variable can be defined within a function, but it can't be seen outside the function - it's within the function scope:
var name = function () {
var something_useful = string;
};
The second example is a closure (it just happens to have a syntax error inside). Minus the bad syntax, your self-evaluating anonymous function looks like this:
(function() {
})();
If you'd like, you can define functions inside this that will be invisible to the outside world. This is useful if you're interested in maintaining a clean global namespace, for example with library code.
(function() {
function utilityFunctionFoo() {
}
function utilityFunctionBar() {
}
})();
Of course, if you'd like to call any of these functions from the outside world, you're out of luck. Or are you? Actually, there's another way to define a function:
var foo = function() {
}
That's exactly the same as writing:
function foo() {
}
...Except that when written in the second style, you can actually omit the var keyword and create a global variable! Bringing it all together:
(function() {
publicData = "stuff accessible from outside anonymous function";
var privateData = "stuff that stays inside anonymous function";
function utilityFunctionFoo() {
}
function utilityFunctionBar() {
}
usefulFunctionExport = function() {
utilityFunctionFoo();
utilityFunctionBar();
}
})();
usefulFunctionExport();
You can't access it after the function it's in terminates. It's a local variable that goes out of scope when its parent function ends.
You should make the main function be a constructor so that it returns a new instance of a class (you could name it Blahdy_blah) with the member function as one of its properties.
Look up constructors, their return values, and accessing member variables.
If you want to execute the function you need to return an object that exposes the function.
var LIB = (function() {
var fn = {
member_function : function(){}
};
return fn;
})();
and to call
LIB.member_function();
(function() {
blady_blah.some_member_function();
})();
If you need to add stuff into it you would write it like this.
(function() {
blady_blah.some_member_function(function(){
// Do stuff...
});
})();