What I have is something like that:
jQuery(function($) {
'use strict';
var App = {
init: function() {
App.startTool();
}
[...]
and when I try to call App.init(); from another file it say that App is not defined.
I'm trying to create some test with jasmine and I've the same error.
How can I go inside this "literal class", nested inside a simple function, from external files?
Javascript has function scope. This means that variables defined within a function are only visible within that function. To access this variable from outside the function, you'll need to either declare it outside the function, attach it to the window or some other global object directly, or return it as a value from the function.
Declaring outside:
var App;
jQuery(function($) {
'use strict';
App = {
init: function() {
App.startTool();
}
[...]
Attaching to the window or other global namespace:
jQuery(function($) {
'use strict';
window.App = { //or namespace.App where namespace can be another global variable.
init: function() {
App.startTool();
}
[...]
The way you're wrapping it you're not going to be able to return the value, but if it was a different function you could do this:
var App= (function() {
'use strict';
var App = {
init: function() {
App.startTool();
}
return App;
}())
A little more on function scope: Variables declared within a function cannot be seen from outside that function. Variables declared outside a function can be seen from inside a function. So if you want an object to be global, you need to declare it outside any function, or set it as a property on something that already has been declared outside the function. In a browser, the window object is global by default. Other environments like nodejs or rhino will have their own global objects.
Its important to understand how JS scope works because its the foundation behind a lot of the more powerful features of the language, particularly closures and the module pattern.
Some people have also mentioned the benefits of namespacing. This is a good point for this context. Having a single global variable for a library or application allows you to avoid conflicts with other libraries or scripts you might be using. You can then attach your other variables to that global namespace variable and reference them as properties of that object. So instead of calling App.init directly, call myProgram.App.init() for instance.
If it is not exposed as a global than you can not touch it.
You would have to put it into some namespace that is in the global scope.
jQuery(function($) {
'use strict';
var App = {
init: function() {
App.startTool();
}
}
if (!window.myNamespace) {
window.myNamespace = {};
}
myNamespace.App = App;
});
The fun thing here is it will not exist until document.ready, not sure why you would want it wrapped with ready. The init call should be called on ready. So you are doing to have race conditions on what widget registers first.
You need to make App globally available if you want to use it from outside the function:
jQuery(function($) {
'use strict';
// attach it to window instead of using var
window.App = {
init: function() {
App.startTool();
}
};
});
Related
I have a couple of variables in my application that I have to use in most of my closures, like variables holding preloaded requests, or variables holding the current state of application (that need to be changed dynamically in different places).
So my application structure looks like this:
(function() {
var MainModule = (function () {
})();
var Utils = (function () {
})();
var Events = (function () {
})();
})();
And I create these variable inside MainModule, but want to change them, remove them, etc, inside Utils and Events. I've been thinking about two ways:
Creating Context closure that keeps an array of those variables, and have get() and set() access methods.
Passing these variables to closures as arguments, but I coulnd't unset them and I'd have difficulties because of the way javascript passes arrays/objects to functions.
How should I handle it?
(function() {
var MainModule = (function () {
var mine;
return {
getMine: function(){ return mine; },
setMine: function(a){ mine = a; }
}
})();
var Utils = (function () {
return function(module){
module.getMine();
}
})();
var Events = (function () {
})();
})();
IIFE does not give anything to put into the MainModule variable so I'm assuming something else will be calling something within Utils. get/set is the safest way to give access to private variables. Like the comments said, IIFE should only be used when needed, otherwise it's just pointless abstraction.
Sorry for the noobish question, but nothing works for me today.
I'm creating a Phonegap application and have intergrated PushWoosh API into my app. And on receive push notification I want to run my previous functions again, so the data will be updated.
Pushwoosh has JS function like this:
document.addEventListener('push-notification',
function(event) {
var title = event.notification.title;
var userData = event.notification.userdata;
var notification = event.notification;
if (typeof(userData) != "undefined") {
console.warn('user data: ' + JSON.stringify(userData));
}
var object = JSON.parse(notification.u);
window.runPushFunctions(object.active, object.open); //Runs a jQuery function I have created..
}
);
Now window.runPushFunctions looks like this:
$(document).ready(function() {
window.runPushFunctions = function(active, open) {
if (active != null || active != undefined) {
$('.hubs-page').removeClass('hubs-active').hide().eq(active).show().addClass('hubs-active');
}
if (open == 2) {
$('html').addClass('hubs-opening');
}
//Trying to run functions from jQuery file that will get data from database and so on..
received();
sent();
checkFriends();
};
});
But I can't for some reason not run received(), sent(), checkFriends().
These functions is set like this in their own files like this:
(function($) {
'use strict';
function checkFriends () {
$.getJSON('url',function(data){
$.each(data,function(index,value){
//Do something with value
});
});
}
Im including files in this order:
file.js -> received(); sent();
file.js -> checkFriends();
file.js -> pushnotifications
Any help will be gladly appreciated
As the other answer here says, you are scoping your method definitions so they are not accessible anywhere outside the containing method.
(function($) {
This is a method definition. Any variables or functions non-globally declared within it cannot be accessed outside it. Therefore, you need to define the functions somewhere else or make them global for them to be accessible.
If you go for defining them somewhere else, you can simply move the function definitions to the top of the same file, outside of the (function($) {})() scope.
If you go for global definitions instead, you need to change the methods' defining lines slightly: instead of
function foo() { }
you need
window.foo = function() { }
This assigns an anonymously declared function to an object in the window scope, which is globally accessible. You can then call it using
window.foo();
or simply
foo();
since it is in the window scope.
I'm not exactly sure I'm understanding your question, but it looks to me like you are defining the function checkFriends inside of a function scope. If you need access to that function definition, you would need to declare it on an object that can be referenced from the global scope. Obviously the easiest way to do that would be to attach it to the window, though there are plenty of reasons not to do that.
window.checkFriends = function(){//code that does stuff};
I'm building a game and was trying to figure out the workings of the melonJS game engine I am using. I'm at a point where I need to create my own version of their CanvasRender object, so was trying to understand what they've done.
Why wrap the canvas renderer in an anonymous, self-invoking function? Can't I just create the function as such?
me.CanvasRenderer = me.CanvasRenderer || {};
me.CanvasRenderer = {
init: function() {
//...
Or even within a namespace:
var CanvasStuff = {
CanvasRenderer : function() {
}
};
CanvasStuff.CanvasRenderer();
I don't understand how they've laid out this code and the purpose. How and when is (function () { invoked?
Here's a snippet of their code: (link to full code)
(function () {
// The canvas renderer object
me.CanvasRenderer = (function () {
var api = {},
var canvas = null,
//...
api.init = function () {
//...
};
return api;
//...
})();
})();
The self-invoking function is executed immediately, so it is similar to the alternatives you posted.
However, the advantage of the self-invoking function is that you can declare variables within that scope that are not accessible outside the closure. For example, in the code snippet you posted there is a var canvas that is accessible within any of the api functions, but not accessible to any outside code. In the first alternative you suggested, there is no way to declare canvas without it being accessible to any clients/callers of the api. Your second alternative (the namespace) isn't filled out enough to see how it would be used, so you might be able to wrap private vars into that closure as well.
I have an oop function in javascript like this:
'use strict';
function oopFunc(){
this.oopMethod(){
console.log('hey it works');
}
}
function foo(){
var init = new oopFunc();
init.oopMethod();
}
function bar(){
var again = new oopFunc();
again.oopMethod();
}
how can I initalize the oopFunc object just once (like a global variable) and use the methods like this?:
'use strict';
function oopFunc(){
this.oopMethod(){
console.log('hey it works');
}
}
function initOopfunction(){
init = new oopFunc();
}
function foo(){
init.oopMethod();
}
function bar(){
init.oopMethod();
}
I have to pass variable parameters to the method but I dont want to initalize a new Object of it for each time I want to use it
EDIT
I need to initalize the function within a other function because the oop function get some parameters which must be typed in by the user
If you want to initialize the common object from a function (although I dont undestand why you want to do that), you can just declare the var in the common scope, and initialize it from somewhere else.
'use strict';
var myObj;
function ObjConstructor() {
this.hey = function () {alert ('hey');};
}
function init() {
myObj = new ObjConstructor();
}
function another() {
init(); // Common object initialized
myObj.hey();
}
another();
Check it here: http://jsfiddle.net/8eP6J/
The main point of 'use strict';, is that it prevents the creation of implicit globals when you don't declare a variable with var. If you declare the variable explicitly, you are good to go.
Take your time and read this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode
Moreover, I would recommend you to wrap your code within a autoexecuted function not to pollute the global scope and avoid collisions with other scripts that might be running in the site. Ideally your whole application should live only in one global variable. And sometimes you can even avoid that. Something like the following:
(function () {
'use strict';
// the rest of your code
})();
So i have link every file needed into the index.html file :
<script src="jquery.js"></script>
<script src="notify.js"></script>
<script src="script.js"></script>
i create an object in 'notify.js' :
var notify = {
newNotification : function(text) {
}
}
script.js :
alert(notify.newNotification);
When i try to access the 'notify' object in 'script.js', it works just fine.But i want to use jquery so i add $(document).ready() to both of the file like this:
notify.js
$(document).ready (
function() {
var notify = {
newNotification : function(text) {
}
}
}
)
Script.js:
$(document).ready (
function() {
alert(notify.newNotification);
}
)
And after i add that, it comes up with notify is not defined.What's wrong? Can anyone explain why it doesn't work?
As you have defined var notify in notify.js inside $(document).ready( which is an anonymous function and var notify scope is limited to this function only .
So it is not accessible outside the $(document).ready( function
To make accessible outside don't wrap it in $(document).ready( function
like this:-
var notify;
$(document).ready(function () {
notify = {
newNotification: function (text) { }
}
});
Like everyone else here already pointed out: Only use $().ready when you're handling DOM-Elements and your Variable is not accessible because you used the var keyword (like you're supposed to). The var keyword limits the defined variables to the current scope, which is the scope of the anonymous function you use as your DOM-Ready-Handler.
So, removing the unnecessary $().read will temporary solve your problem.
BUT(!) you should wrap your code into a closures to avoid messing up the global scope and to avoid possible naming conflicts with 3rd-party code.
Like that:
notify.js
;(function ($, window, undefined) {
var notify = {
newNotification : function(text) {
return text;
}
};
})(jQuery, this);
script.js
;(function ($, window, undefined) {
alert(notify.newNotification());
})(jQuery, this);
So, now you'll have the same problem as before, you don't have access to your Object.
Sure you could just add your notify Object to the global scope as Arun P Johny suggested in his answer, but i'm pretty sure over the time there will be more Object you'll need to make global accessible.
If you put each of them in the global scope, you start messing up the global scope again, so my recommendation would be ONE global Object that will hold all other objects/variables you need globally accessible. (Or even better use something like requirejs
Somethink like this:
main.js
;var MyApp = {}; # Only variable in global scope
# Maybe some more initalization code here, dunno
notify.js
;(function ($, window, undefined) {
MyApp.notify = {
newNotification : function(text) {
return text;
}
};
})(jQuery, this);
script.js
;(function ($, window, undefined) {
alert(MyApp.notify.newNotification());
})(jQuery, this);
Some interesting Q/A's about scope and closures here on stackoverflow:
What is the scope of variables in JavaScript?
How do JavaScript closures work?
JavaScript closures vs. anonymous functions
A good Answer about messing around with the global scope:
What is meant by “leaking” into global scope?
In this case there is no need to wrap the notification object in dom ready... because from the looks of it you are not creating any dom element reference while creating the object... the only thing that matters is any method invokation that deals with dom element has to be done on dom ready.
var notify = {
newNotification: function (text) {}
}
$(document).ready(function () {
notify.newNotification()
})
if you declare the variable inside a dom ready handler then it becomes a local variable to the dom ready handler... so it will not be accessible outside the dom ready handler...
Another solution is to add the variable to the global scope within the dom ready handle like
var notify;
$(document).ready(function () {
notify = {
newNotification: function (text) {}
}
})
or
$(document).ready(function () {
window.notify = {
newNotification: function (text) {}
}
})
You only need one document.ready
And this only declare the variables that will move freely in their scripts.
See the example:
script.js:
$(document).ready(function(){
// declare the variables as global
$.varA, $.varB, $.varC;
});
notify.js:
function doNotify(){
// your code here
$.varA = /*your code here */
}
function otherFunc(txt){
// your code here
$.varB = txt;
}
All of your JavaScripts will load before the document is ready.
Create a separate function in script.js that references the notify object, then call that function from $(document).ready
Try this.
var notify = {
newNotification : function(text) {
}