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.
Related
So the basic setup of the function I want to access is
(function (self, $) {
function init() {
...
}
function stuff() {...
}
self.onload = init;
}
})(window, jQuery);
So if possible how would I call any of these functions from the console? For example I want to do
stuff("things");
One of my ideas to access this is to completely remove the function wraping the game code and running init myself, but I wasn't sure how to get my code to replace the code already on the page.
Your functions are inside a closure you'd have to make them global or accessible from a global object to make them accessible from the console straight away. e.g.
var myprogram = (function (self, $) {
function init() {
...
}
function stuff() {...
}
self.onload = init;
return {
stuff: stuff
};
})(window, jQuery);
now you could call myprogram.stuff() from the console. However I wouldn't recommend this break in encapsulation if your not doing it for testing.
You can also set break points using your debbuger and then call them from the console, which would be my recommendation, see the links below for more information.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger
https://developer.mozilla.org/en-US/docs/Tools/Debugger
For debugging purposes, you could add the functions to the window scope like so:
(function(self, $) {
function stuff() {
...
}
window.stuff = stuff; // Remove this line in production
})(window, jQuery);
Now you can call stuff() from the console.
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'm trying to wrap a JavaScript object literal in a self executing anonymous function. The first code example below works fine, but the second doesn't and I'm not really sure why?
Works:
(function(){
return MyApp = {
init: function() {
console.log('MyApp init');
}
}
})();
Doesn't Work:
(function(){
var MyApp = {
init: function() {
console.log('MyApp init');
}
}
return MyApp;
})();
As I understand things, the SEAF should execute and immediately return. That's why the first example returns MyApp as an object I can interact with. I thought assigning MyApp to a variable inside the SEAF and then returning it would do the same thing but in:
Uncaught ReferenceError: MyApp is not defined
Why?
Since the result of your SEAF (better named IEFE) is not used anywhere, it doesn't really matter what the function returns. Now compare
(function(){
MyApp = {…}
})();
with
(function(){
var MyApp = {…}
})();
The difference is that in the second function your variable is preceded by a var keyword which makes it local to the IEFE, while in the first function it is an implicit global (which you should avoid). That way, the second snippet doesn't assign to anything in the global scope, and accessing MyApp later from outside will fail with the error.
Better return some value that you then assign to a globally declared variable:
var MyApp = (function(){
return {…};
})();
What your first example is doing is setting MyApp as a global variable - since the variable MyApp is not preceded by a var keyword or dot notation, it becomes global. It sounds like that's not actually an issue for you if you're putting MyApp in a self-executing function - you can really just remove the return statement from it - or even define other globals in the same function. You don't ever reference the result of your top-level function, so there's no use of that return.
Your second example sets MyApp as a local variable using var, so it's visible only inside of the context of the function that's running it.
Solution using arrow functions:
var myApp = (() => {
return {
init: () => console.log('MyApp init')
};
})();
myApp.init();
Explanation:
The global variable myApp is set to the result of an IIFE (Immediately-invoked Function Expression).
init can also be written as an arrow function.
If no other logic is performed in an arrow function before the return statement, and it returns an object literal, it can be further simplified. To return an object literal from an arrow function, wrap it in parentheses:
var myApp = (
() => ({
init: () => console.log('MyApp init')
})
)();
I have inherited a code base that I need to update for my job. I'm slowly learning what they are trying to accomplish with the closure that is in place, but I am getting stuck when trying to update a part of the site that uses this functionality. I'll give a basic outline of what the code is trying to accomplish and see if anyone can help.
var TheObject = (function (){
var veryLargeDependantData = {
var1: {},
var2: {},
var3: [],
//Set these variables via functions
function1: function f1(data){...},
function2: function f2(data){...},
initialize: function initialize() { //set values for var1... var3}
};
return {initialize: veryLargeDependentData.initialize};
})().initialize();
Since I obviously cannot show production code on the site this will have to do. But basically the veryLargeDependentData variable is the entrance to the function. When the page loads it calls the initialize function and everything is happy. But now I need to add this to an onclick event for and older page and the firebug console says that the variable is undefined. In the other pages I am able to use it with no problem.
My question is what magic is going on that causes the closure not to be part of a callable namespace such as this. I'm a bit of a javascript nOOb so I apologize if the question sounds misguided.
onclick='TheObject.initialize();'
I assume what you mean is that you want to run the initialize function in a click event handler, and you're currently attempting to do so like this:
TheObject.initialize();
If that's the case, the problem is that TheObject actually refers to the return value of initialize, since you called initialize on the return value of the immediately-invoked function expression. And the chances are that initialize is returning undefined (most likely, it has no explicit return statement).
To solve this, you probably want to remove the immediate call to initalize, which will allow you to use the line shown above both on page load and anywhere else.
In this code, the value of TheObject will be whatever the veryLargeDependentData.initialize() method returns. If the initialize method returns nothing, TheObject will be undefined.
A simplified example:
var TheObject = (function () {
return {
initialize: function () {
// stuff happens here, but importantly, there's nothing returned
}
}
})().initialize();
You can break this down into the following order of execution:
// the value of step_one is a function that will return an object when it is run
var step_one = (function () {
return {
initialize: function () {
// ...
}
}
});
// after running the function step_one, step_two will be an object
// containing one key - initialize - which is a function
var step_two = step_one();
// since initialize doesn't return anything, TheObject is set to undefined.
var TheObject = step_two.initialize();
You can get around this by setting TheObject to be the object containing the initialize method then run that method again whenever you need it.
var TheObject = (function () {
return {
initialize: function () {
}
}
})();
// initialize
TheObject.initialize();
// and again
TheObject.initialize();
PLEASE NOTE!
The original author may have intended for the initialize method to only be run once. Running it more than once might introduce bugs into your system!
Seems unnecessarily complicated, I'm not sure what is gained by using the anonymous function and closure in this case. Is there any reason you can't simple do the following?
var TheObject = {
var1: {},
var2: {},
var3: [],
//Set these variables via functions
function1: function(data){...},
function2: function(data){...},
initialize: function(){alert("initialize");}
};
var initButton = document.getElementById("initButtonName");
initButton.addEventListener("click", TheObject.initialize);
Note that you'd want to remove the inline event.