(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}
Related
When I tried the example on babel Symbol in the example there was no return, so I added it cause I thought it should be(I am not sure if I am right).
It logged in my console MyClass is not defined.
If IIFE returns a Class, why it said MyClass is not defined?
(function() {
var key = Symbol("key");
function MyClass(privateData) {
this[key] = privateData;
}
MyClass.prototype = {
doStuff: function() {
}
};
return MyClass //this is no return for the original example
})();
var c = new MyClass("hello")
c["key"]
As with any other function call, the value goes to the left hand side of the function.
var return_value_of_x = x();
or
var return_value_of_iife = (function () { return 1; })();
Since you have nothing on the LHS of your IIFE, the value is discarded.
In your example MyClass is a variable declared within the IIFE. It doesn't exist outside that function. You could create another variable with the same name in the wider scope:
var MyClass = (function () { …
You can store the value somewhat like this if your IIFE is returning a value.
let returnedValue = (function(){console.log('return'); return 2;})();
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();
If I declare a function literal:
var x = function(){
alert('hi');
};
console.log(x); // returns the function code.
However:
var x = (function(){
alert('hi');
})();
console.log(x); // returns undefined?
I don't understand why this happens. Isn't the point of writing a function as a literal is to still be able to access it by its variable reference name? I know this may be silly but I'm just learning javascript so don't judge too harshly.
Your function does not return anything, so its return value is undefined.
A self-executing function is executed and the function is not stored anywhere - only its return value survives (and any external variables the function sets/modifies).
For example, this code would be equivalent to var x = 'hi';:
var x = (function(){
return 'hi';
})();
The purpose of self-invoking functions is usually to create a new scope, e.g. when creating callback functions in a loop:
for(var i = 0; i < 5; i++) {
window.setTimeout(function(){ alert('i = ' + i); }, 1000 * i);
}
This would use the same i in all callbacks so it would alert i = 5 5 times.
for(var i = 0; i < 5; i++) {
(function(i) {
window.setTimeout(function(){ alert('i = ' + i); }, 1000 * i);
})(i);
}
By using a self-executing function we create a new scope and thus a new i in each loop.
Another use of self-executing functions is to create a new scope where certain variables are ensured to be available and set to the correct value:
(function($, window, undefined) {
// here the following always applies:
// $ === jQuery
// window === the global object [assuming the function was executed in the global scope]
// undefined is well, undefined - in some js engines someone could have redefined it
})(jQuery, this);
If you:
var foo = somefunction;
… then you assign a function to foo.
If you:
var foo = somefunction();
… then you assign the return value of a function call to foo
Your function:
function(){
alert('hi');
}
… has no return statement, so it will return undefined.
to call a function at the same time it's defined, i had been using:
var newfunc = function() {
alert('hi');
};
newfunc();
is the following the correct way of combining these 2:
var newfunc = function() {
alert('hi');
}();
There could be a number of reasons you wish to do this. I'm not sure what yours are, but let me introduce a couple of favourite patterns:
Pattern #1: A singleton. The function is executed and then becomes a singleton object for use by other components of your code.
var singletonObject = new function() {
// example private variables and functions
var variable1 = {};
var variable2 = {};
var privateFunction = function() {
};
// example public functions
this.getData = function() {
return privateFunction(variable1, variable2);
};
// example initialisation code that will only run once
variable1.isInitialised = true;
};
Pattern #2: Self-executing anonymous function ... handy for sooo many reasons!
// Declare an anonymous function body.
// Wrap it in parenthesis to make it an "expression.
// Execute it by adding "();"
(function(){})();
And here's an example that also creates a namespace for your objects.
I'm using "NS" as an example namespace:
// declare the anonymous function, this time passing in some parameters
(function($, NS) {
// do whatever you like here
// execute the function, passing in the required parameters.
// note that the "NS" namespace is created if it doesn't already exist
})(jQuery, (window.NS = window.NS || {}));
You can also set the context of a self-executing function by using .call or .apply instead of the usual parenthesis, like this:
(function($){
// 'this' now refers to the window.NS object
}).call(window.NS = window.NS || {}, jQuery);
or
(function($){
// 'this' now refers to the window.NS object
}).apply(window.NS = window.NS || {}, [jQuery]);
var newfunc = function f() {
alert("hi!");
return f;
}();
Having a named function expressions allows the function to recursively call itself or, in this case, return itself. This function will always return itself, however, which might be an annoyance.
No. Your second example will immediately call the anonymous function and assign its return value to newfunc.
adamse describes an approach which appears to work. I'd still avoid the approach as the two step process is easier to read and thus will be easier to maintain.
If I understand your question correctly, give this a try:
(f = function (msg) {
msg = msg ? msg : 'default value';
alert(msg); }
)();
f('I\'m not the default value!');
You'll get two alerts, the first one will say "default value" and the second will say "I'm not the default value. You can see it in action at jsBin. Click 'preview' to make it run.
you could do like this:
o = {};
o.newfunc = ( function() {
function f() {
alert('hi');
}
f();
return {
f : f
};
}
)();
then calling the function like:
o.newfunc.f();
will also render an alert message
How to pass current scope variables and functions to the anonymous function in plain Javascript or in jQuery (if it's specific for frameworks).
For example:
jQuery.extend({
someFunction: function(onSomeEvent) {
var variable = 'some text'
onSomeEvent.apply(this); // how to pass current scope variables/functions to this function?
return null;
_someMethod(arg) {
console.log(arg);
}
}
});
Should log in firebug everything from the function above:
jQuery.someFunction(function(){
console.log(this.variable); // or console.log(variable);
console.log(this._someMethod(1); // or jQuery.someFunction._someMethod(2);
});
Thanks!
Read about Scopes in JavaScript for example in "Java Script: The good parts".
In the Java Script there is only scope inside Functions.
If you specify your variable inside function with var you can't access them from outside of this function. This is way to make private variables in JavaScript.
You can use this variable, that point to current object you are in (this is not a scope itself). But! if you initiate function without new command, than this will point to outer scope (in most cases it's window object = global scope).
Example:
function foo(){
var a = 10;
}
var f = foo(); //there is nothing in f
var f = new foo(); //there is nothing in f
function bar(){
this.a = 10;
}
var b = new bar(); //b.a == 10
var b = bar(); //b.a == undefined, but a in global scope
Btw, check out syntax of apply method Mozilla docs/apply
So you can see, that fist argument is object, that will be this when your method will be called.
So consider this example:
function bar(){
console.log(this.a);
console.log(this.innerMethod(10));
}
function foo(){
this.a = 10;
this.innerMethod = function(a){
return a+10;
}
bar.apply(this);
}
var f = new foo(); // => you will get 10 and 20 in the console.
var f = foo(); // => you will still get 10 and 20 in the console. But in this case, your "this" variable //will be just a global object (window)
Maybe it's better to make
var that = this;
before calling apply method, but maybe it's not needed. not sure
So, this definitely will work:
function foo(){
console.log(this.a);
}
jQuery.extend({
somefunc: function(func){
this.a = 10;
func.apply(this);
}
});
$.somefunc(foo); //will print 10.
Before line 1:
var that = this;
Then change line 4:
onSomeEvent.apply(that);