Is it possible to pass namespace as parameter in javascript function? - javascript

I have 3 .js files. The main Home.js and two other .js files, for instance Page1.js, Page2.js
Home.js:
var Home= {
Sample: function (pageId,data) {
pageId.MergePageData(data);
}
}
Page1.js:
var Page1 = {
MergePageData: function (data) {
// do something
}
}
Page2.js:
var Page2 = {
MergePageData: function (data) {
// do something
}
}
I tried calling like this by passing it as a string:
Home.Sample('Page1', 'data');
Home.Sample('Page2', 'data');
But I guess as it is being passed as a string am getting an error
"Object doesn't support property or method 'MergePageData' "
I need to differentiate the call between the two functions in two different js files. How to achieve that?

The pageId in your function is just a variable, and when you call it you specify the type of this variable, and as you pass "Page1", which is a String it is just a string without having anything to do with your real Page1 object. but there are some options that can help you out.
The Other point that you have to consider is, it doesn't matter you have 2 or 3 different js files. the important point is if all your javascript codes are injected to single html page, then you can have all your code in all the JavaScript files in single window context. So if you define something in a global scope which is window, you can have access to it all over your JavaScript code.
It seems your Page1 and Page2 are global objects, so you can do it like:
var Home= {
Sample: function (pageId,data) {
window[pageId].MergePageData(data);
}
}
but I guess data vriable is not a global, you have 2 options, first make it global or just store it in a storage like:
localStorage.setItem("data", JSON.stringify(data));
then change your Sample function like this:
var Home= {
Sample: function (pageId,data) {
window[pageId].MergePageData(JSON.parse(localStorage.getItem("data")));
}
}
Although you have to be very careful about the size of your data object, if it is a big object with a lot of properties and inner objects, you should reconsider and change your solution.

Basically you want to create your object Home inside an IIFE. That way you can pass in any library or object namespace throughout several files.
For your Home object, declare and run an anonymous function, assign your object directly to the the window object. This will be your "namespace" and accessible throughout your files by window.Home. Use this file to initialize your Page objects. As for now the DOM ready event is used from jQuery.
// #param ($): jquery library 1.10.2
(function ($) {
// 1. ECMA-262/5
'use strict';
// 2. PRIVATE CONFIGURATION
var cfg = {
// an object literal to store config
page2: {
page: 'page2',
data: 'data'
}
};
// 3. GLOBAL OBJECT NAMESPACE
window.Home = {
init: function(){
// initialize your other files
this.cache = {
page1: new Home.Sample();
page2: new Home.Sample(cfg.page2);
}
}
};
// 4. ONCE THE DOM IS READY
$(function () {
Home.init();
});
}(window.jQuery));
Then for your other files, a slightly different approach can be used.
// #param ($): jquery library 1.10.2
// #param (home): Home namespace
window.Home = (function ($, home) {
// 1. ECMA-262/5
'use strict';
// 2. CONFIGURATION
var cfg = {
page: 'page1'
data: 'data'
};
// 3. CONSTRUCTOR FUNCTION
home.Sample = function (options) {
this.settings = $.extend({}, cfg, options);
this.init();
};
// 4. PROTOTYPE OBJECT
home.Sample.prototype = {
init: function(){
this.cacheItems();
this.mergePageData(settings.data);
},
cacheItems: function(){
this.page = settings.page;
},
mergePageData: function (data) {
// do something with this.page and data
// consider caching data instead of passing it along
}
};
// 5. GLOBALIZE OBJECT
return home;
}(window.jQuery, window.Home || {}));
This approach is modular and better to maintain. Since the whole configuration is extracted from the logic you will find it easier to create different instances of an object. Simply by passing in options into your Sample object you can change the whole data/structure but keeping behavior as intended. You can fill in options from your server language and use the sizzle selector engine inside jQuery todo powerful DOM traversing and so on ...

Related

How to reference the calling Javascript module?

I am using what I understand to be the Javascript module pattern, and jQuery.
I have an app which has a public and an admin side. Each has its own JS file, though some functionality is shared so I have extracted it to a common file. Gulp combines the common + public files into a single file for use on the public side, and the common + admin files into a single file for use on the admin side.
The public JS file includes something like:
var PublicFoo = (function () {
var bar = function() {
// ..
};
var init = function() {
$button.on('click', Common.someCommonThing);
};
return {
init: init
};
})();
The HTML page where this code is needed fires it off like so:
<script>
PublicFoo.init();
</script>
The admin JS file includes something very similar, also defining a bar() function, and calling the same Common module function.
var AdminFoo = (function () {
var bar = function() {
// ..
};
var init = function() {
$button.on('click', Common.someCommonThing);
};
return {
init: init
};
})();
The common JS file (shared and combined with both public and admin JS) includes something like:
var Common = (function () {
var someCommonThing = function() {
// Do stuff.
// When done, I want to call bar() in the calling module.
// This does not work, throws 'Uncaught ReferenceError: bar is not defined'
bar();
};
return {
someCommonThing: someCommonThing,
// ...
};
})();
From the Common module, how can I reference a function in the calling module?
I know about .caller, but apparently that is non-standard and should not be used.
I could maybe somehow pass in the name of the calling module as a parameter to Common, and reference it, but that seems ugly:
// In PublicFoo
var init = function() {
$button.on('click', function() {
Common.someCommonThing(PublicFoo)
});
};
// In Common
var someCommonThing = function(callingModule) {
// ...
callingModule.bar();
I could also of course extract the bar() call out and do it back in the calling module, but that doesn't seem so neat either:
// In PublicFoo
var init = function() {
$button.on('click', function() {
Common.someCommonThing();
bar();
});
};
// ... and the same thing in AdminFoo
I feel like this must be JS modules 101, a basic requirement, and yet I can't seem to find anything about it, though I may be searching using the wrong terminology. Or is the reason I can't find how to do this because it should not be done this way?
How can I reference the appropriate bar() from the Common module?
I know about .caller, but apparently that is non-standard and should not be used.
Also it doesn't work in your case, as the caller is the event handler and neither PublicFoo nor AdminFoo.
I could maybe somehow pass in the name of the calling module as a parameter to Common, and reference it
Yes, passing references to the thing that you want to be called is the way to go if you want someCommonThing to do different things after it has finished. Notice you really should only use such a callback when the thing is asynchronous, otherwise just returning and calling bar afterwards (like in your last snippet) is much easier.
How can I reference the appropriate bar() from the Common module?
If both bars might be loaded at once into the page, then there's no way around a parameter that references the callback.
However, that doesn't seem to be the case in your example - on one page, AdminFoo takes the role of Foo and on the other page PublicFoo takes the role of Foo.
So just reference only Foo.bar from Common! Let the respective pages fill it with the appropriate value, i.e.
var Foo = AdminFoo
on the admin page and
var Foo = PublicFoo
on the public page.
Passing functions to other functions is very common and perfectly idiomatic JavaScript, so you could do it like this:
// In PublicFoo
var bar = function() {
// ..
};
var init = function() {
$button.on('click', function() {
Common.someCommonThing(bar)
});
};
// In Common
var someCommonThing = function(bar) {
// ...
bar();
};

Call minified browser javascript in node

I have an enormous minified javascript file (with no browser specific calls) but several functions that I need to use. Is there a systematic way to convert such a file so that it is callable in node? The js is wrapped in a self executing anonymous function. The function ends with .call(this)
The very least you would need to do is export something from that file, so you could load it as a module and consume it from your other Node code.
exports.myThing = somethingFromMyFile;
As per your description, I am assuming that the file is of the format
(function () {
// file contents
this.someFunction = function() {
// function contents
}
}).call(this);
When executed in the browser window object gets passed as this and all the properties like someFunction are attached to window.
To use it as a module in node, you could bind the function to an empty object and export that object. For example,
var obj = {};
(function () {
// file contents
this.someFunction = function() {
// function contents
}
}).call(obj);
module.exports = obj;
Then use it like
var mymodule= require('./mymodule');
mymodule.someFunction();

JavaScript init function and its use

I'm new to JavaScript and saw a coode where a init function is used while declaring the object..I tried searching for "JavaScript init functions" but it does not take me to any correct document. Also, it does not provide me the exact application of this function…
I have modelled a function on how it looks like
var1 = Class.extend({
init : function(){ alert ('Hi'}
}
Question:
How does init does called? Is it similar to the init(initialization) method in Object oriented concepts.
Can you please provide a example on how init function could be called?
init is a custom function name, it may be called by the framework or by the object constructor and usually keeps place of a post construction method. For instance I declare it for jQuery plugins, like this:
;(function($, window, document, undefined) {
// Create the defaults once
var pluginName = "Display", defaults = {
cols : 32,
rows : 16
};
// The actual plugin constructor
function Display(element, options) {
// Object variables
this.options = $.extend({}, defaults, options);
this.size = {};
// Post construct
this.init();
}
// methods of the Display
display.prototype = {
init : function() {
this.setSize(this.options.rows, this.options.cols);
},
setSize : function(rows, cols) {
// calculates size
}
};
// JQuery Plugin declaration
// ...
})(jQuery, window, document);
With this, a call (from the correct scope) to new Display() will call the init method.
Init in most framework is used to be called after the object initialization. It is called automaticaly so you just put in the code you want to execute after the object is initialized. It is similar to constructor however it is not the same. For an example in backbone which is cool javascript framework (you see this init functions only in frameworks it is not native javascript method)
Constructor runs before Backbone sets up the structure. initialize is called inside the structure's constructor function. So basically if you need to augment anything before Backbone sets up the structure, use constructor if you need to augment anything after Backbone sets up the structure use initialize.

Protect functions and var names on a javascript code

Im designing an API that requires my users to download a javascript file from my server and then load it on their pages. Inside this file there is a function call generic(), if my users include this js and for some reason they have a piece of js on their page where there is another function call generic() this will represent an issue. Im not a front end dev, I know that with php you can solve this creating a class and putting all your functions inside, so you can call them like $myclass->myfunction();, but how can i solve this on js? Is this even a good approach on js? (no jquery please.)
You will obviously always have to expose at least one identifier globally, but a common approach is to wrap everything in an immediately-invoked function expression:
var YourNamespace = (function () {
var privateData = 10; // Not accessible outside the IIFE
// Expose public properties (these functions can access the private data)
return {
someMethod: function () {
// Do stuff
},
anotherMethod: function () {
// More stuff
}
};
}());
This will expose a single identifier, YourNamespace, as an object with properties that can be used as methods. You can use it like this:
YourNamespace.someMethod();
Wrap your code inside a wrapper object/ or function.
var MyLibrary = {
global1: 123,
global2: 'abc',
doSomething: function(a){
// ...
},
somethingElse: function(b){}
};
If u are looking for Encapsulation in Javascript, then u are looking for Closures

encapsulating javascript inside a namespace

I'm looking to encapsulate my javascript inside a namespace like this:
MySpace = {
SomeGlobal : 1,
A: function () { ... },
B: function () { ....; MySpace.A(); .... },
C: function () { MySpace.SomeGlobal = 2;.... }
}
Now imagine that instead of a few lines of code, I have about 12K lines of javascript with hundreds of functions and about 60 globals. I already know how to convert my code into a namespace but I'm wondering if there's a quicker way of doing it than going down 12K lines of code and adding MySpace. all over the place.
Please let me know if there's a faster way of doing this.
Thanks for your suggestions.
I like to wrap up the namespace like so. The flexibility is huge, and we can even separate different modules of the MySpace namespace in separate wrappers if we wanted too. You will still have to add some sort of _self. reference infront of everything, but at least this way you can change the entire name of the namespace very quickly if need be.
You can see how with this method you can even call _self.anotherFunc() from the 1st module, and you'll get to the second one.
(function (MySpace, $, undefined) {
var _self = MySpace; // create a self-reference
_self.test = function () {
alert('we got here!');
_self.anotherFunc(); // testing to see if we can get the 2nd module
};
_self = MySpace; // reassign everything just incase
}(window.MySpace = window.MySpace || {}, jQuery));
$(function () {
MySpace.test(); // call module 1
MySpace.callOtherModule(); // call module 2
});
// Here we will create a seperate Module to the MySpace namespace
(function (MySpace, $, undefined) {
var _self = MySpace; // create a self-reference
_self.callOtherModule = function () {
alert('we called the 2nd module!');
};
_self.anotherFunc = function () {
alert('We got to anotherFunc from the first module, even by using _self.anotherFunc()!');
};
_self = MySpace; // reassign everything just incase
}(window.MySpace = window.MySpace || {}, jQuery));​
jsFiddle DEMO
Wrap a function body around your existing code to use as scope, hiding everything from global - this will allow you to do internal calls without pasting Namespace. prefix everywhere, neatly hide things you don't want everyone else to see, and will require minimal changes as well.
After that, decide what functions you want to "export" for everyone and assign them to properties of object you want to use as "namespace".

Categories

Resources