logging javascript module names - javascript

I want to be able to log my module initializations to see what happens. Is there a way to get the module namespace and log it to the console.
(function($, bis, window, document, undefined) {
"use strict";
//other app code
bis.library = bis.library || function(module) {
$(function() {
if (module.init) {
module.init();
//how can I make it log the module namespace
console.log('module' + module.toString() + 'initialized');
}
});
return module;
};
//other app code
})(jQuery, window._bis = window._bis || {}, window, document);
example of my module definition
(function($, bis, window, document, undefined) {
"use strict";
var common = bis.common,
urls = bis.urls,
defaults = bis.defaults,
createWorklist = bis.createWorklist,
editWorklist = bis.editWorklist,
editMoveBoxesWorklist = bis.editMoveBoxesWorklist;
bis.worklist = bis.worklist || bis.library((function() {
// module variables
var init = function() {
//module init code
};
//other module code
return {
init: init
};
})());
})(jQuery, window._bis = window._bis || {}, window, document);​
So I want the line console.log to log the following text "module bis.worklist initialized" for example.

I did as Pointy suggested. I have added a name property to my modules and just use the
console.log(module.name);

Related

Potential dangers of enabling classwide globals (Javascript)?

I have a question regarding the relative safeness of designing Javascript types that use class static/global variables. For example, suppose we had:
function whatever()
{
if(whatever.initialized === undefined)
{
whatever.global_setting = 1024;
whatever.initialized = true;
}
}
whatever.prototype.get_global_setting = function()
{
return whatever.global_setting;
}
whatever.prototype.set_global_setting = function(setting)
{
whatever.global_setting = setting;
}
Now if only one developer/team were to be using the library then whatever nonsense they decide to do on a class-wide scale wouldn't be such a big issue.
But what if we have scripts from several organizations running in a single webpage (ad partners and such) all of which are accessing the library from the same codebase (eg: "XYZ.com/scripts.js")? Will they all get their own private copy or is there even the slightest possibility that it might be shared? If so, then providing an interface for global settings could lead to some pretty serious problems!
EDIT
Just to be clear, my library is actually defined more along the lines of this:
var whatever =
(
function()
{
"use strict";
function internal_whatever()
{
if(internal_whatever.initialized === undefined)
{
internal_whatever.global_setting = true;
internal_whatever.initialized = true;
}
}
internal_whatever.prototype.get_global_setting = function()
{
return internal_whatever.global_setting;
}
internal_whatever.prototype.set_global_setting = function(setting)
{
internal_whatever.global_setting = setting;
}
return internal_whatever;
}
)();
if(typeof module !== "undefined" && module.hasOwnProperty("exports"))
{
module.exports = whatever;
}
Does that totally mitigate the issue, or are there still some corner-cases?
Well, you could use namespace scope instead of global scope. Like plugins do.
Simplified something like this:
;var Modules = (Modules === undefined) ? {} : Modules;
Modules.whatever = {
_nonecares: 1234,
whatever: function(){
return this._nonecares
}
};
console.log(Modules.whatever._nonecares);
This is how the newest jquery does it:
(function(global, factory){
"use strict";
// Pass this if window is not defined yet
})(typeof window !== "undefined" ? window : this, function( window, noGlobal){
"use strict";
// Expose jQuery and $ identifiers, even in AMD
// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
// and CommonJS for browser emulators (#13566)
if( !noGlobal ){
window.jQuery = window.$ = jQuery;
}
return jQuery;
});

Which JavaScript would have better performance?

(function (window, $, undefined) {
"use strict";
var methods = {};
var thingOnPage = $('.class');
methods.init = function () {
};
methods.1 = function() {
};
methods.2= function() {
};
methods.3= function() {
};
if (thingOnPage.length > 0) {
methods.init();
}
}(window, jQuery));
This gets compiled and included on every page, but the init method will only be called if there is a specific class on the page.
My question is, would I be able to make this more efficient if the conditional statement wrapped the declaration of all the methods?
Thanks

Typescript idiom to prevent duplicate modules included in a page

Suppose I have a TypeScript module defined like:
module Foo {
export var now = new Date();
}
This gets transpiled to:
var Foo;
(function (Foo) {
Foo.now = new Date();
})(Foo || (Foo = {}));
If I were writing in pure JavaScript, I would have included something like:
var Foo;
(function (Foo) {
if (window.Foo) return; // <-- PREVENT DUPLICATES!
Foo.now = new Date();
})(Foo || (Foo = {}));
to ensure that this module gets defined only once even if the <script/> gets included multiple times in a page. How do I achieve the same effect in TypeScript?
If you are writing your whole program in TypeScript, the compiler checks this for you...
module Foo {
export class X {
go() {
alert('First');
}
}
}
module Foo {
export class X { // Duplicate identifier X
go() {
alert('Second');
}
}
}
If you can, using external modules along with a module loader (RequireJS for example) ensures that non of your code needs to be added to the global scope, so it wouldn't conflict...
import foo = require('./foo');
export class Y {
go() {
return new foo.X();
}
}
Compiles to:
define(["require", "exports", './foo'], function(require, exports, foo) {
var Y = (function () {
function Y() {
}
Y.prototype.go = function () {
return new foo.X();
};
return Y;
})();
exports.Y = Y;
});
From this discussion on TS forums, I was able to come up with the following solution:
module window {
if (window.Foo) return;
export module Foo {
export var now = new Date()
}
}
This compiles to:
var window;
(function (window) {
if (window.Foo)
return;
(function (Foo) {
Foo.now = new Date();
})(window.Foo || (window.Foo = {}));
var Foo = window.Foo;
})(window || (window = {}));

Typescript generating redundant variable

Consider the following Typescript code:
module demoAppModule{
'use strict';
export module nest{
export var hello = function () {
alert('Hello!');
};
}
}
demoAppModule.nest.hello();
After transpiling we have the following javascript code:
var demoAppModule;
(function (demoAppModule) {
'use strict';
(function (nest) {
nest.hello = function () {
alert('Hello!');
};
})(demoAppModule.nest || (demoAppModule.nest = {}));
var nest = demoAppModule.nest;
})(demoAppModule || (demoAppModule = {}));
demoAppModule.nest.hello();
Why is this line generated? It hurts my eyes.
var nest = demoAppModule.nest;
Short Answer: Its needed to access the module variable locally. E.g.
module demoAppModule{
'use strict';
export module nest{
export var hello = function () {
alert('Hello!');
};
}
// The following would not be possible without that line
console.log(nest.hello);
}
demoAppModule.nest.hello();
Longer Answer: Its similar to the var added before a module e.g. notice var x:
// TypeScript
module x{export var foo;}
// Generated JavaScript
var x;
(function (x) {
x.foo;
})(x || (x = {}));
But when you are inside a module + export a module the var needs to be added to outermodule.innermodule so you do not do var innermodule upfront. You add it to outermodule and then create a local variable to point to the innermodule which you can see in the generated javascript:
// Notice var here
var demoAppModule;
(function (demoAppModule) {
'use strict';
// Notice no var here
(function (nest) {
nest.hello = function () {
alert('Hello!');
};
})(demoAppModule.nest || (demoAppModule.nest = {}));
// Notice var assinged afterwards
var nest = demoAppModule.nest;
// The following would not be possible without that line
console.log(nest.hello);
})(demoAppModule || (demoAppModule = {}));
demoAppModule.nest.hello();

JavaScript Namespace

I want to create a global namespace for my application and in that namespace I want other namespaces:
E.g.
Dashboard.Ajax.Post()
Dashboard.RetrieveContent.RefreshSalespersonPerformanceContent();
I also want to place them in seperate files:
Ajax.js
RetrieveContent.js
However I have tried using this method, however it won't work because the same variable name is being used for the namespace in 2 seperate places. Can anyone offer an alternative?
Thanks.
You just need to make sure that you don't stomp on your namespace object if it's already been created. Something like this would work:
(function() {
// private vars can go in here
Dashboard = Dashboard || {};
Dashboard.Ajax = {
Post: function() {
...
}
};
})();
And the RetrieveContent file would be defined similarly.
Here is a very good article on various "Module Patterns" in JavaScript. There is a very nice little section on how you can augment modules, or namespaces and maintain a cross-file private state. That is to say, the code in separate files will be executed sequentially and properly augment the namespace after it is executed.
I have not explored this technique thoroughly so no promises... but here is the basic idea.
dashboard.js
(function(window){
var dashboard = (function () {
var my = {},
privateVariable = 1;
function privateMethod() {
// ...
}
my.moduleProperty = 1;
my.moduleMethod = function () {
// ...
};
return my;
}());
window.Dashboard = dashboard;
})(window);
dashboard.ajax.js
var dashboard = (function (my) {
var _private = my._private = my._private || {},
_seal = my._seal = my._seal || function () {
delete my._private;
delete my._seal;
delete my._unseal;
},
_unseal = my._unseal = my._unseal || function () {
my._private = _private;
my._seal = _seal;
my._unseal = _unseal;
};
// permanent access to _private, _seal, and _unseal
my.ajax = function(){
// ...
}
return my;
}(dashboard || {}));
dashboard.retrieveContent.js
var dashboard = (function (my) {
var _private = my._private = my._private || {},
_seal = my._seal = my._seal || function () {
delete my._private;
delete my._seal;
delete my._unseal;
},
_unseal = my._unseal = my._unseal || function () {
my._private = _private;
my._seal = _seal;
my._unseal = _unseal;
};
// permanent access to _private, _seal, and _unseal
my.retrieveContent = function(){
// ...
}
return my;
}(dashboard || {}));
The Yahoo Namespace function is exactly designed for this problem.
Added:
The source of the function is available. You can copy it into your own code if you want, change the root from YAHOO to something else, etc.
There are several libraries that already offer this sort of functionality if you want to use or examine a pre-baked (that is, a tested) solution.
YUI.attribute and YUI.base
dojo.mixin
underscore.extend
jQuery.extend
goog.provide and goog.object.extend
The simplest and most bug free one to get going with is probably jQuery.extend, with the deep argument set to true. (The reason I say it is bug free is not because I think that jQuery.extend suffers from less bugs than any of the other libraries -- but because it offers a clear option to deep copy attributes from the sender to the receiver -- which most of the other libraries explicitly do not provide. This will prevent many hard-to-diagnose bugs from cropping up in your program later because you used a shallow-copy extend and now have functions executing in contexts you weren't expecting them to be executing in. (If however you are cognizant of how you will be extending your base library while designing your methods, this should not be a problem.)
With the NS object created, you should just be able to add to it from where ever. Although you may want to try var NS = NS || {}; to ensure the NS object exists and isn't overwritten.
// NS is a global variable for a namespace for the app's code
var NS = NS || {};
NS.Obj = (function() {
// Private vars and methods always available to returned object via closure
var foo; // ...
// Methods in here are public
return {
method: function() {
}
};
}());
You could do something like this...
HTML page using namespaced library:
<html>
<head>
<title>javascript namespacing</title>
<script src="dashboard.js" type="text/javascript"></script>
<script src="ajax.js" type="text/javascript"></script>
<script src="retrieve_content.js" type="text/javascript"></script>
<script type="text/javascript">
alert(Dashboard.Ajax.Post());
alert(Dashboard.RetrieveContent.RefreshSalespersonPerformanceContent());
Dashboard.RetrieveContent.Settings.Timeout = 1500;
alert(Dashboard.RetrieveContent.Settings.Timeout);
</script>
</head>
<body>
whatever...
</body>
</html>
Dashboard.js:
(function(window, undefined){
var dashboard = {};
window.Dashboard = dashboard;
})(window);
Ajax.js:
(function(){
var ajax = {};
ajax.Post = function() { return "Posted!" };
window.Dashboard.Ajax = ajax
})();
Retrieve_Content.js:
(function(){
var retrieveContent = {};
retrieveContent.RefreshSalespersonPerformanceContent = function() {
return "content retrieved"
};
var _contentType;
var _timeout;
retrieveContent.Settings = {
"ContentType": function(contentType) { _contentType = contentType; },
"ContentType": function() { return _contentType; },
"Timeout": function(timeout) { _timeout = timeout; },
"Timeout": function() { return _timeout; }
};
window.Dashboard.RetrieveContent = retrieveContent;
})();
The Dashboard.js acts as the starting point for all namespaces under it. The rest are defined in their respective files. In the Retrieve_Content.js, I added some extra properties in there under Settings to give an idea of how to do that, if needed.
I believe the module pattern might be right up your alley. Here's a good article regarding different module patterns.
http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth
I highly recommend you use this technique:
https://github.com/mckoss/namespace
namespace.lookup('com.mydomain.mymodule').define(function (ns) {
var external = namespace.lookup('com.domain.external-module');
function myFunction() {
...
}
...
ns.extend({
'myFunction': myFunction,
...
});
});
I've been using this pattern for a couple of years; I wish more libraries would do the same thing; it's made it much easier for me to share code across my different projects as well.
i wrote this function to simplify creating namespaces. Mabey it will help you.
function ns(nsstr) {
var t = nsstr.split('.');
var obj = window[t[0]] = window[t[0]] || {};
for (var i = 1; i < t.length; i++) {
obj[t[i]] = obj[t[i]] || {};
obj = obj[t[i]];
}
}
ns('mynamespace.isawesome.andgreat.andstuff');
mynamespace.isawesome.andgreat.andstuff = 3;
console.log(mynamespace.isawesome.andgreat.andstuff);
bob.js can help in defining your namespaces (among others):
bob.ns.setNs('Dashboard.Ajax', {
Post: function () { /*...*/ }
});
bob.ns.setNs('Dashboard.RetrieveContent', {
RefreshSalespersonPerformanceContent: function () { /*...*/ }
});
Implementation:
namespace = function(packageName)
{
// Local variables.
var layers, layer, currentLayer, i;
// Split the given string into an array.
// Each element represents a namespace layer.
layers = packageName.split('.');
// If the top layer does not exist in the global namespace.
if (eval("typeof " + layers[0]) === 'undefined')
{
// Define the top layer in the global namesapce.
eval(layers[0] + " = {};");
}
// Assign the top layer to 'currentLayer'.
eval("currentLayer = " + layers[0] + ";");
for (i = 1; i < layers.length; ++i)
{
// A layer name.
layer = layers[i];
// If the layer does not exist under the current layer.
if (!(layer in currentLayer))
{
// Add the layer under the current layer.
currentLayer[layer] = {};
}
// Down to the next layer.
currentLayer = currentLayer[layer];
}
// Return the hash object that represents the last layer.
return currentLayer;
};
Result:
namespace('Dashboard.Ajax').Post = function() {
......
};
namespace('Dashboard.RetrieveContent').RefreshSalespersonPerformanceContent = function() {
......
};
Gist:
namespace.js

Categories

Resources