I have been using JS Modular pattern throughout the application. The modules look like the following:
var moduleName = {
prop1 : 'value1',
prop2 : 'value2',
fun1Name : function () {
// body of funName
moduleName.fun2Name(); // notice the way I am calling the function using moduleName
// Didn't use this.fun2Name()
},
fun2Name : function () {
// body of functName
}
};
And inside the modules, I have been accessing the functions using moduleName.functionName() which may also be accessed (as we all know) using this.functionName(). Now I am refactoring the code and I was just curious to know that:
Is there any reason that I should change moduleName.functionName() to this.functionName() wherever possible?
Are there any performance issues associated with both the ways of calling the module functions?
What's the best way to call the module functions inside the module itself?
It makes your code reusable between different but similar objects (typically instances of the same constructor function)
No
That's subjective
This is a JS newbie questions, I am working with a parent namespace Base and I include all my code within this namespace.
file model.js
Base = {}
Base.Observer = {
method1 : function(){//...},
method2 : function(){//...}
};
Base.Bot = function(name){
this.name = name;
this.somefunc = function(){};
}
file presenter.js
Base.Presenter = {
}
file helper.js
Base.Helper = { };
Now my problem is I would like to keep this module private. Without allowing any user access through any browser tools like firebug. So I could only think of wrapping them within a self executing anonymous function and making Base into a local variable which would lead to the presenter.js and helper.js not being able to access the Base namespace.
I would like to keep the files separate as it helps in keeping code organizated but I can't seem to figure what is the correct way to do this. Would appreciate any help on this.
Thank you
So I could only think of wrapping them within a self executing anonymous function and making Base into a local variable
That is the usual approach
which would lead to the presenter.js and helper.js not being able to access the Base namespace.
The function should return Base; which you then assign to a global.
See the module pattern
A while ago, I offered-up a JavaScript design pattern (the Module Pattern - see below) that I got from a John Resig example as part of a solution to someone’s question and I received the following comment:
“…that pattern is a bit over
engineered and not that good. Still
leaking into global-scope. and your
not opening yourself to async loaders.
But it is better then just ad-hoc
coding !”
So…
If “leaking” into global scope means “your object gets appended to the browsers window (object)”…then everything already gets appended (globally):
This “leaks” into global scope:
window.jQuery
…just call: window.jQuery and it resolves as a function();
This “leaks” into global scope:
function HelloWorld() { alert(‘Howdy’); }
…just call: window.HelloWorld() and you will get ‘Howdy’.
This “leaks” into global scope:
var myVariable = 10;
…just call: window.myVariable and you will get 10
If the commenter is correct, then all the above “leak” into global-scope. So, personally, I don’t see a way NOT to “leak” into global-scope as even your form controls exists there (as well).
As such, here are my questions…
What is meant by “leaking” into
global-scope?
Why is that bad?
How do you avoid it?
When wanting to create persistent
custom-objects, why is the Module
Pattern (below) bad?
Design patterns let you encapsulate
complex logic, is encapsulation
suddenly bad simply because we’re
writing in JavaScript?
Or...is this commenter simply wrong?
Here is the Module Pattern I Mentioned Above:
<script type="text/javascript">
var myNamespace = (function($) {
var publicInstances = {};
// ***********************
// myObject
publicInstances.myObject = myObject;
function myObject() {
/// <summary>A pointer to this</summary>
var self = this;
this.someProperty = new String();
this.initialize = function() {
/// your code here
}
this.someMethod = function() {
/// your code here
}
self.initialize();
}
return publicInstances;
})(jQuery);
jQuery(document).ready(function() {
// Use would look like
var myInstance = new myNamespace.myObject();
});
</script>
UPDATED:
I’m satisfied with the answers below and want to thank everyone for taking the time to comment.
TO RECAP THE ANSWERS BELOW:
"Leaking" into global-scope occurs when something used in local-scope is unintentionally made available to the global-scope (e.g. the window object). This is bad because it opens the page to potential naming collisions which could result in variables resolving to unexpected values or types.
Intentionally making a variable global is not considered a "leak". However, properly namespacing the object is required to reduce potential for said naming collisions.
You cannot avoid globally-scoped variables, but you can reduce the above risks by using asynchronous-loaders and defining-modules made available in plug-ins like RequireJS or Curl.
"Leaking" into global scope is when something used in a local scope is unintentionally made available to the global scope. That means assigning to a variable not already defined in the current scope:
function myFunction() {
a=1;
}
myFunction();
alert(a);
//-> 1
It's bad because there could be naming collisions resulting in variables with different values/types than expected. It can also lead to a bug in older Internet Explorers when you forget to use the var keyword for a variable used in a for statement.
I wouldn't class intentionally making a variable global as "leaking", because it's more like you're "pouring" it into the global scope. However, this is still often considered bad practice by some (although I think that's a little melodramatic) because there are still potential naming collisions with current properties of the window object, or variables set by other scripts and libraries.
[[Short story]]
Don't make global variables ever and use an async module loader like requirejs or curl
[[Long story]]
That comment was poorly structured.
There is nothing wrong with the module system. I was complaining about using global variables at all. (I still think the full generic module pattern is bloated).
Whether you should avoid all global variables is a different question and I think a matter of style. You can either use an async loader to pass modules around or using window to pass modules around.
What is meant by “leaking” into global-scope?
What I meant was your creating global variables. Minimising the use of global variables is a pattern. In functional style programming it's possible to have zero global variables but this is a different pattern from using global modules.
Why is that bad?
Having any state globally can cause that state to be corrupted.
How do you avoid it?
You can't. You can minimize the amount of global variables though. To avoid having global state completely you can use asynchronous loaders. These define a few global variables for you that you can then use.
When wanting to create persistent custom-objects, why is the Module Pattern (below) bad?
There is nothing wrong with the module pattern. The problem is storing your module globally. The issue is having global namespaces.
Design patterns let you encapsulate complex logic, is encapsulation suddenly bad simply because we’re writing in JavaScript?
Now that I've cleared up the intent of the comment this question isn't really relevant
Or...is this commenter simply wrong?
The comment was poorly phrased at best. I objected to global namespaces rather than modules, but did not state this properly.
The alternative is using asynchronous loaders and defining modules. These can be narrowed down to two global variables. define and require.
require = function(moduleName, callback)
This will get a module and then return it to you.
define = function(obj)
this defines a module.
The concept here is that you multi file code as follows:
// main.js
require([
"foo.js",
"bar.js",
...,
], function(foo, bar, ...) {
// do stuff
});
//foo.js
(function() {
var namespace = modulePatternCode;
...
define(namespace):
})();
//bar.js
(function() {
var namespace = modulePatternCode;
...
define(namespace):
})();
Your module only "leaks" it's namespace holder so it's pretty acceptable.
Loader example using RequireJS:
Define a utilities module in utils.js:
define(function () {
return {
each: function (iterable, callback) {
// ...
},
map: function (iterable, mapper) {
// ...
}
};
});
Use the above module in another module, say math.js:
define([ "utils" ], function (utils) {
return {
sum: function (numbers) {
var sum = 0;
utils.each(numbers, function (n) {
sum += n;
});
return sum;
},
average: function (numbers) {
return this.sum(numbers) / numbers.length;
}
};
});
And you can use math.js in another file, say main.js:
console.log("About to add 1-3");
require([ "math" ], function (math) {
console.log(math.sum([ 1, 2, 3 ]));
});
You can still have namespaces, and still keep them warm and cozy inside modules:
namespace.js:
define([ "foo", "bar", "moo" ] function (foo, bar, moo) {
return {
foo: foo,
bar: bar,
moo: moo
};
});
Then the rest of the modules can use this namespace during definition:
define([ "namespace" ], function (namespace) {
namespace.foo(42);
});
Or at runtime, in some other module:
define(function () {
return {
initialize: function () {
require([ "namespace" ], function (namespace) {
namespace.foo(42);
});
}
};
});
In the usages above, nothing but define and require are global. Of course, these are just illustrative examples, as there are many different flavors of defining/using modules in RequireJS.
I am writing a web application which uses YUI3 for all it's JS needs. I need functionality such as Tooltips, Tooltips whose content is determined by AJAX queries, Toggle Buttons and so on.
I was not sure who to build an architecture to achieve all this. I have taken the following approach
var Myapp = function(){
this.toggleButton(node,config)
{
YUI().use(....,function(Y){
//code to convert NODE into a toggle button;
});
}
return this;
};
In my application I then just convert all the buttons into toggle buttons by calling
var app = Myapp();
app.toggleButton(Y.all('.toggle-buttons'),{'text1':'TOGGLE_ME','text2':'TOGGLED_ME'});
All this works. But I wanted to know from more experienced developers if there is anything fundamentally wrong with this approach.
Is this a good way to use JavaScript ?
return this;
This is unneccesary since function constructors return this by default.
var app = Myapp();
You forgot to call new Myapp() without the new keyword this will be the window object and you are effectively writing to global scope.
There's a fundamental problem in your code:
var MyApp = function(){
this.toggleButton(node,config)
{
...
You're not defining a function for MyApp. Instead, you try to invoke toggleButton each time you instantiate it. It should fail because the function is undefined
In your case, Class definition and instantiation is not needed because MyApp is being used as a utility.
You can define MyApp as a static Object:
var MyApp = {
toggleButton: function toggleButton() {
// your code
}
};
And you can use it anywhere by:
MyApp.toggleButton();
I have been trying to get namespaces to work with backbone.js for the last hour or so.
I have read: How do I declare a namespace in JavaScript?
And I tried all approaches. Here is the problem:
Backbone.Controller wants to be initialized through a constructur ("new keyword"), because otherwise Backbone.history won't be set. This is the code that I'm trying to put into a namespace, for example "Site.Controllers"
var MainController = Backbone.Controller.extend({
routes: {
"help": "help", // #help
},
help: function(){}
});
var ws = new MainController
Whenever I try to put the MainController into some namespace, backbone.js complains that MainController is not a constructor - of course it does, because there doesn't seem to be any way to make a namespace "tree" with constructor functions. If you guys want, I can list all the approaches I tried, but it's exactly the same as from the link provided above. I didn't try putting it into closures, because that is suggested to be very slow.
var namespace = {
MainController: Backbone.Controller.extend({ ... }),
HelpController: Backbone.Controller.extend({ ... }),
...
};
I'm confused as to what your trying to achieve. An almost fail proof method of creating a namespace is :
var namespace = (function() {
...
return {
...
};
})();
Also yes closures are indeed slower. But I would not worry about this unless your creating the closures millions of times.