Is there a way to make function created inside a closure accessible outside of the closure? I'm working with an AIR app and I need to provide access to the specialFunction() to AIR but the closure is keeping that from happening.
(function () {
... a bunch of code ..
function specialFunction() {
.. some code
}
}());
You can assign the function to the global object (which is window in browsers):
(function () {
... a bunch of code ..
window.specialFuncton = function() {
.. some code
}
}());
This makes it globally available.
If the AIR application also needs access to other functions, then it is better to create a namespace for these functions:
var funcs = {}; // global
(function () {
... a bunch of code ..
funcs.specialFuncton = function() {
.. some code
}
}());
Related
I'm creating a wrapper for an API that will be used in a couple different applications.
I'm using a global object and placing the various functions into that object as different keys. So I'll have:
window.globalContainer = {
APIEndpoint1: function(){
make API call and resolve result
},
APIEndpoint2: function(){},
...
}
All the meat of the API calls are directly in the functions. That is, you could go to window.globalContainer.APIEndpoint1 from the console and see the entire function.
Is this generally bad practice for something that's used across multiple applications and acts as a helper library? Or is this acceptable? I looked at jQuery in the console and it seemed to do much of the same. If it is frowned upon, how do I implement private functions within the global object?
A good place to start is anonymous closures:
(function (global) {
var foo = global.foo || {};
//accessible
foo.publicVar = 5;
foo.publicFcn = function (a, b) {
privateFcn(a, b);
...
};
//not accessible
var privateVar = 5;
function privateFcn(a, b) {
...
}
global.foo = foo;
})(window)
With these you can pretty intuitively build a library and not pollute the namespace.
You explicitly say which variables and functions you want to be made accessible.
You can use an IIFE to implement private functions/properties.
window.globalContainer = function () {
//what ever you define here is not accessible outside. Only the API in
//the returned object is accessible outside
function private1() {
make API call and resolve result
}
return {
APIEndpoint1: function(){
private1();
},
APIEndpoint2: function(){},
...
}
}();
Suppose there is a global variable which is a function
function MyClass(){}
and there are methods of this class such as
MyClass.func1 = function()
{
}
I want to ensure that YUI compression and obfuscation works without putting entire class inside a closure like
(function () {
function MyClass(){}
MyClass.func1 = function()
{
}
})();
Is there a way to make YUI compression work without doing this?
Well, I suppose you could wrap it in an anonymous function before compressing it, and then just remove the anonymous function after.
Also make sure you're using prototype ;)
(function () {
function MyClass(){}
MyClass.prototype.func1 = function()
{
}
})();
Results in:
(function(){function a(){}a.prototype.func1=function(){}})();
And just take out the anonymous function:
function a(){}a.prototype.func1=function(){}
I have been writing javascript for a while now and more recently been playing with coffeescript. I noticed that coffeescript compiles functions in the following way:
(function() {
}).call()
I have also noticed people write functions in this way:
(function() {
})()
From what I understand these are anonymous functions that call themselves. Firstly, what is the difference in between having .call() and just () is .call() just a more semantic way of writing ().
Also why does coffeescript wrap the entire file in an anonymous function, when it isn't usually necessary? Are there any performance or other advantages to this? When should these sort of self calling anon functions be used?
Thanks
Using .call() changes the context of the IIFE to the this value of the parent scope.
The first this will be [object Window], the global scope in browser environments:
(function () {
console.log(this);
})();
The second, will be the exact same:
(function () {
console.log(this);
}).call(this);
The difference is that in ECMAScript 5's strict mode, the first example this will be undefined:
(function () {
'use strict';
console.log(this); // undefined
})();
However when using Strict Mode and .call(), this is again the global scope with the correct this context:
(function () {
'use strict';
console.log(this);
}).call(this);
Here's a jsFiddle showing this. The main difference is that the normal IIFE loses it's this context, some CommonJS platforms evaluate files with a specific this.
CoffeeScript does this to ensure that your code has the same this context as the scope where it's placed (the parent scope) - because functions don't normally inherit their this object from the surrounding context.
Using the pattern(s) above, you should wrap your function logic in there to avoid placing all your code in the global scope and having variable/naming conflicts, to which you can then create things such as Modules and return only the APIs that you need, for instance:
var Module = (function () {
'use strict';
return {
someMethod: function () {
// do something
}
}
})();
// call it:
Module.someMethod();
Each function creates it's own scope, so wrapping your blocks of code in these will protect your variable/function names from conflicting with eachother. We can also access "private" methods from within these closures:
var Module = (function () {
'use strict';
var _privateMethod = function () {};
return {
someMethod: function () {
_privateMethod();
}
}
})();
We would do this when we don't want the methods to be publicly accessible by our users too.
I have a bunch of functions in my script which resides in a .js file.
How can avoid conflicts with the names of my functions within the same page if some other script written by some other guys use the same function names as in my script ?
Is there a way to do this?
If you don't need access to those functions outside of your script you can wrap the whole script in an immediately invoked function expression:
(function () {
// Your code here
}());
This introduces a new scope, so any declarations within it are not visible outside of it.
If you do need access outside of that scope, expose your functions as methods of a "namespace":
var YourStuff = (function () {
// Private functions etc...
// Expose public methods
return {
someMethod: function () {}
};
}());
By taking this approach you only introduce a single global identifier, reducing the chances of a conflict. You can call the method as follows:
YourStuff.someMethod();
Use namespaces..
var company = {};
company.doSomething = function() {
};
company.project = {};
company.project.submodule = {};
company.project.submodule.doSomething = function() {};
My basic setup is a whole heap of Javascript under an anonymous self-invoking function:
(function () {
...
})();
My problem is that I can't seem to get access to the objects within this ASI function via the DOM tab. I tried both the following:
var MYAPP = function () {
...
};
var MYAPP = (function () {
...
})();
The first didn't fire at all. The second just said MYAPP is undefined in the DOM tab.
Is there a way around this?
In your first version, you are simply creating a function with the name MYAPP, but you are not executing it.
In the second version, your function is executed and its result is assigned to MYAPP. But your function does not seem to return anything, so MYAPP stays undefined.
See A Javascript Module Pattern on YUIBlog for an explanation of this pattern. Their example goes like this:
YAHOO.myProject.myModule = function () {
return {
myPublicProperty: "I'm accessible as YAHOO.myProject.myModule.myPublicProperty.",
myPublicMethod: function () {
YAHOO.log("I'm accessible as YAHOO.myProject.myModule.myPublicMethod.");
}
};
}(); // the parens here cause the anonymous function to execute and return
So your function basically returns an object containing all the public members. You can then access these with Firebug, too.