So this is the first time I am using Javascript in a much more powerful context, having a thick client and doing much of the heavy-lifting through javascript in itself. I am using jQuery, and a lot of the code is getting muddy at the moment coz it's all just a bunch of functions.
Turns out for some of my functions, I required variables to be passed through multiple functions with their value being maintained. The obvious way of doing this is by declaring them outside of the scope of the function and then have the function manipulate it the way it ought to . (These variables are objects and not primitive type, so I guess javascript being pass by reference, this works).
For instance, I probably have something like this
var node = //init with some value;
$(document).ready(setup);
function setup()
{
A();
B();
}
function A()
{
// operate on var node
}
function B()
{
// operate on var node
}
This is obviously a scaled down version of my code, but captures the way I deal with global variables. My question is, is there a more elegant way to do the above ?
Thanks
Any reason why you can't do:
$(document).ready(function() {
var node = //init with some value;
setup(node);
function setup(node) {
A(node);
B(node);
}
function A(node) {
// operate on var node
}
function B(node) {
// operate on var node
}
});
In general, using global variables and functions is a bad idea and should be avoided wherever possible.
Note that while you appear to have been asking specifically about node, your functions setup, A and B are also all global variables in your version.
The simplest approach would be to put all these declarations inside an anonymous function:
$(document).ready(function() {
var node = ...;
function A() {
...
}
function B() {
...
}
function setup() {
A();
B();
}
setup();
});
Only use one global variable (or as few as possible). Make any functions or objects members of your one global variable.
Douglas Crockford says
An objective measure of the quality of a JavaScript program is How
many global variables and global functions does it have? A large
number is bad because the chance of bad interactions with other
programs goes up. Ideally, an application, library, component, or
widget defines only a single global variable. That variable should be
an object which contains and is the root namespace for all of your
stuff.
Yahoo’s single global is YAHOO. It is spelled in all caps to identify
it as something special, since all lower case is ordinary and initial
caps indicates a constructor. Being in all caps, it is unlikely that
someone would use it accidentally, which further reduces the
likelihood of collision.
http://www.yuiblog.com/blog/2006/06/01/global-domination/
Also, you can create objects to further organize your code.
GLOBAL.myObject = {};
GLOBAL.myObject.myFunction = ...
I prefer the "revealing module" pattern:
var myApp = (function () {
// privates
var node;
var a = function () {
// operate on node
};
var b = function () {
// operate on node
};
// publics
var init = function () {
// initialization stuff
a();
b();
};
return {
init: init
};
})();
$(document).ready(function () {
myApp.init();
});
This way you only ever have one global, myApp, which stores everything else your app needs.
I think it makes the code harder to understand, I'd much rather take the variable in as an argument and have it as a return.
$(function(){
var outcome = multiply(add(5));
});
function add(num)
{
return num+1;
}
function multiply(num)
{
return num*5;
}
If you feel like you absolutely want to have global variables wrap your stuff in a closure so it doesn't actually go to a global scope.
ie,
(function(){
var a; // can be used in any functions within this closure, but not polluting window
function A()
{
a = 'blah';
}
})();
There are many. For instance, objects.
// jQuery shorthand for "wait till DOM ready"
$( function() {
// create node object
var node = {
id: /* some value */,
setup: function() {
this.A();
this.B();
},
A: function() {
// operate on this.id
},
B: function() {
// operate on this.id
}
};
// setup node object
node.setup();
} );
Global variables are trouble waiting to happen. Don't dirty up your global namespace. Javascript is an object oriented language, use objects. Notice your object can have a property that you can reference with the this keyword from within the objects methods.
Related
I've got 3 codes :
var control = new Control();
function Control() {
this.doSomethingElse = function() {...}
this.doSomething = function () {
control.doSomethingElse();
}
}
Or
var control = new Control();
function Control() {
var self = this;
this.doSomethingElse = function() {...}
this.doSomething = function () {
self.doSomethingElse();
}
}
Or
var control = Control();
function Control() {
var self = this;
this.doSomethingElse = function() {...}
this.doSomething = function () {
self.doSomethingElse();
}
return self;
}
Important : The function is a controller, and just declared once. Then I'm using "control" everywhere in my code...
I was wondering if the control.doSomethingElse() was slow ?
In the end, what is the right thing to do and/or the fastest code in those exemple ?
Thanks !
The first is wrong - an object should never internally use the variable name by which it is known outside. Other code could change that variable to point to something else, breaking this code.
The third is also wrong - when calling Control() without new the assignments to this.foo inside will end up getting attached to the global object (except in strict mode, where there's no implicit this on bare function calls, so the assignment to this.doSomethingElse tries to attach to undefined, causing a runtime error).
That only leaves the second as appropriate, but ultimately it's a question of correctness, not performance.
Do not define methods in constructor - that means defining them every time an instance is created. Use Control.prototype.foo = function() {} instead. Also you do not need to return this if you're using new operator - that's the whole point of new operator.
The recommended approach is this:
function MyClass(param1) {
// Here we're changing the specific instance of an object
this.property1 = param1;
}
// Prototype will be shared with all instances of the object
// any modifications to prototype WILL be shared by all instances
MyClass.prototype.printProperty1 = function() {
console.log(this.property1);
}
var instance = new MyClass("Hello world!");
instance.printProperty1(); // Prints hello world
To understand this code, you need to understand javascript's prototype-based inheritance model. When you create instance of MyClass, you get a new object that inherits any properties present in MyClass.prototype. Read more about it.
Also I wonder:
The function is a controller, and just declared once.
If you're not using this multiple times, you don't need to create something like class. You can do this instead:
var control = {doSomething:function() { ... }};
I assume you are used to Java, where everything must be a class, whether it makes sense or not. Javascript is different, you can also make single objects or functions as you need.
I've got the first file in my code directory as follows
myNamespace.js
var myNamespace = {};
Then my subsequent files can look as one of the two following ways.
first
(function (ns) {
ns.DoStuff = function(){
// do stuff
}
})(myNamespace);
second
myNamespace.DoStuff = function(){
//do stuff
}
So what is the difference between these two methods? Both seem to work for me. Is there a more generally accepted convention?
sorry, still new to javascript
Your first approach will not work. It would create DoStuff on the global object (most likely window). You would need to replace this with ns, after you did that, there is no difference between the two approaches.
The former will have the adventage that you might be able to closure all your application/file related stuff into that outer self-invoking closure function. So you won't clobber the global namespace.
(function (ns) {
var foo = 10,
bar = 42;
ns.DoStuff = function(){
console.log('foo is ', foo, ' and its not available globally');
}
})(myNamespace);
You have an error in your first one, you've used this where I'm pretty sure you meant ns:
ns.DoStuff = function() {
};
Leaving that aside, your first approach tends to be better because you've created a nice little scoping function for yourself, which allows you to have private data and functions available to all of the public methods you create on your namespace, without making them globals. E.g.:
(function(ns) {
function privateFunction() {
}
ns.DoStuff = function() {
privateFunction(); // <=== works fine
};
})(myNamespace);]
privateFunction(); // <=== doesn't work, because it's private
I like doing it that way partially because I have thing against anonymous functions, and so I wouldn't define DoStuff as above, but rather like this:
(function(ns) {
ns.DoStuff = Namespace$DoStuff;
function Namespace$DoStuff() {
}
})(myNamespace);
Now the function I've assigned to myNamespace.DoStuff has a proper name, which helps me out when I'm debugging my code. But that name doesn't pollute the global namespace, which helps me stay sane and avoid conflicts with other code.
Long story short, I have a long code that uses jQuery. Lots of files, functions, etc. A less than ideal amount of our users are having issues with our code because some addons, toolbars and the like they have installed breaks our JavaScript code because of jQuery gets included twice and nasty stuff like that.
I thought I could just
Include jQuery
Use $.noConflict
Then include the whole rest of my code between something like:
.
(function($) {
// All of my code goes here.
})(jQuery);
I haven't checked if this fixes our issues with those users, but it does work. The problem is, in one part of the site (image upload) we have an iframe that needs to call some of those functions defined in our big chunk of code. I've tried putting those functions out of this unnamed function call, but it uses, on itself, other functions which have to be there.
Any idea or workaround of how could I be able to access functions defined inside that function (shown above) from a code that's outside of it?
Thanks!
You cannot access a function context from the "outside world". Well, to be accorate you could do it in some older js engines which allowed for accessing .__parent__ attributes, but that is old'n'busted and no longer available.
However, you would need to either expose some functions within your closure, or you creating a namespace object where you write all of your logic in (which also has to be available in the parent context).
So I'd suggest something like
(function( $ ) {
function myFunc() {
// do stuff
}
function anotherFunc() {
}
window.myFunc = myFunc; // expose myFunc globally
}( jQuery ));
Maybe even better:
var myNameSpace = { };
(function( $ ) {
myNameSpace.myFunc = function() {
// do stuff
};
}( jQuery ));
// somewhere else
myNameSpace.myFunc();
It is not an ideal practice, but you can declare those functions in the global scope.
(function($) {
globalFunct = function (arg1, arg2) { // Don't use var keyword
...
};
})(jQuery);
It isn't ideal because you can run into naming collisions, much like you are observing with jQuery. Improve upon this approach by putting all of your globally-accessible methods in a "package." Choose a unique name for it. This will prevent collisions.
// Somewhere outside of your anonymous function, in the global scope
var myPackage = {};
(function($) {
myPackage.globalFunct = function (arg1, arg2) {
...
};
})(jQuery);
Then call that method by invoking myPackage.globalFunct().
Why are you wrapping your code in a call to the jQuery function object which you pass in to your self-executing anonymous function; are you meaning to create a jQuery object from all of your code?
In order to expose your code to the outside world, you need to assign your functions and objects to an object which is outside of the scope of your code, such as the window object.
For example, if you had created an object containing various methods and properties that you wanted to expose, you could do this:
//Your self-executing anonymous function
(function($)
{
//Object which contains various useful methods and properties
var useful = {...};
//Expose it to the outside world
window.Useful = useful;
})(jQuery);
EDIT: as others have noted, it is not an ideal solution as you will indeed run into naming collisions if you are not careful. Also, using an object external to your anonymous function as a namespacing object (as others have stated) is my preferred method
Yes, you can "export" the function from within a closure:
Yes, you can "export" the function from within a closure:
(function() {
function a() {
console.log("a");
}
function b() {
a();
console.log("b");
}
// make b globally available
window.b = b;
})();
b();
window.PARTY_CATS_jQuery = jQuery.noConflict(true);
(function($) {
$(function() {
// All of my code goes here.
});
})(COMPANY_NAME_jQuery);
Then just use PARTY_CATS_jQuery in your global functions
If you feel PARTY_CATS_ is not a unique enough name pick something safer like BABY_KILLER_jQuery
I have a Javascript Object structured after the Module Pattern. I have several private function in it which are called from other sibling "private" functions. How can I access another variable/function without the potential to accidentally access a global/external variable/object/function?
function doSomething() {
alert("Something I don't want to do");
}
var My.Namespaced.SingletonClass = (function() {
var init = function() {
doSomething();
}
var doSomething = function() {
alert("Something I want to do");
}
return {
"init": init;
}
})();
My.Namespaced.SingletonClass.init();
My guess is that the above code would in fact access the correct, inner doSomething function, but I'd like some more security than that. How can I explicitly address the inner/nested function without fear of accidentally calling functions or addressing objects in the scope around my singleton?
Short version: you can't. If doSomething isn't defined as a sibling of init, then JavaScript will search successively broader scopes until it finds a doSomething function, or it runs out of scopes to search.
Longer version: you can prevent this sort of behavior by using a private object to hold your private helper functions, like this:
function doSomething() {
alert("Something I don't want to do");
}
// Assuming My.Namespaced is already defined:
My.Namespaced.SingletonClass = (function() {
var helpers = {};
helpers.doSomething = function() {
alert("Something I want to do");
}
var init = function() {
helpers.doSomething();
}
return {
init: init
}
})();
My.Namespaced.SingletonClass.init();
I'm not sure if it's important that the helper functions are truly siblings (but I don't see why that would particularly matter).
Also keep in mind that My and My.Namespaced need to be defined before you tack on SingletonClass - and there's no need to use JSON-style quoting for keys in the object you're returning.
How can I define a function's prototype in JavaScript? I want to do this like I would do it in C where you would do something like:
void myfunction(void);
void myfunction(void){
}
So is there any way to do this in JavaScript? I'm asking this because of the function declaration order that is required in JavaScript.
Edit:
I have an object:
function something(){
var anArrayOfSomethingObjects;
aPrivateFunction(){
// does some stuff
anArrayOfSomethingObjects[3].aPublicFunction();
}
return {
functionA: function() { },
aPublicFunction: function() { },
functionC: function() { }
}
}
privateFunction needs to access publicFunction which is declared afterwards.
How can I do this?
JavaScript is dynamic language there is no need to do that. Meaning Javascript has dynamic binding and dynamic typing, so the check will be on the run time. So no need to define forward declaration like in static languages.
Reply to edit:
Even in this case you still do not need to define forward declaration. Once object will have that method or field in run-time it will work fine. But you probably tackled to the problem of scoping in JavaScript, assuming you asking your question after something gone wrong.
you have to really understand what is a dynamic language, and why your question doesn't really make a lot of sense. your problem is not about 'definition vs. declaration' like on C, it's most about statements order.
in JavaScript (as with most dynamic languages) a function definition like this
function whatever (params) {
...
}
is in fact syntactic sugar for an assignment statement like this:
whatever = function (params) {
...
}
as you can see, whatever is in fact a variable, and it's assigned a function value. so you can't call it before assigning it.
Of course, execution order doesn't have to follow lexical order. If that's your case, you just have to make sure you assign the needed variable before using it. If it's a local variable and you want closure semantics, you can define it first and assign later, like this:
var myfunc = undefined;
function first () {
...
myfunc (...);
...
}
myfunc = function (...) {
...
}
What you are looking for is the Module pattern:
function Something()
{
var someObjects;
var pub = {};
var privateFunction = function()
{
pub.publicFunction();
}
pub.functionA = function() {};
pub.functionB = function() {};
pub.publicFunction = function() {};
return pub;
};
More info and examples: http://www.wait-till-i.com/2007/08/22/again-with-the-module-pattern-reveal-something-to-the-world/