The problem I have is that there are a set of variable values / properties in one file and a library in another file. I have started refactoring the code but still need to keep variable values(dynamic) and library(static) differently.
I am using namespacing and overall want only one global namespace.
The problems I have at the moment:
1. How can I still keep one global namespace
2. What is the best way to read the values from one file and use it in the library present in another file.
e.g I came up with something like
//File ONE with values
var main.dynamicvalues = (function(){
var a = 10,
b = 20,
c = 30;
return {
a:a,
b:b,
c:c
}
}());
//File TWO with core Library
var main.library = (function(){
//Various Private functions that need to use a,b,c variables from above main.dynamicvalues namespace
return {
//Public functions again need to use a,b,c from above namespace.
}
}());
Is there a way I can have a pattern so that I keep only one global namespace and can refer to variables directly without having to use maincode.values.a, maincode.values.b, maincode.values.c or something like this in maincode.library.functions
Thanks
Sparsh Gupta
This approach is a little better, but it's not exactly what you're looking for.
var main = {};
main.dynamicvalues = (function() {
// same as before
})();
main.library = (function(dyn){
// use dyn.a, dyn.b etc
return {
// same in here
}
}(main.dynamicvalues));
Create a new file (maybe name it something like "common.js") and put the values there.
You can try RequireJS. This will let you do what you want with no global namespace at all (if you'd like to). In addition it will give you non-blocking script loading, easy way to handle dependencies and a build tool.
On the other hand, it can deprive you of the joy of investigating things for your own and better understanding of js architectural patterns.
Your code with RequireJs could have looked like this:
// File one with values, let's name it values.js
define([], function() {
var a = 10,
b = 20,
c = 30;
return {
a: a,
b: b,
c: c
}
})
// File two with library
define([
// load values.js as a dependency
'values'
// what is returned in values.js can be passed as an argument to the callback
], function( values ) {
values.a === 10 // true
})
Related
I'm requiring different files at the top of my main script in node. All my require statements are hoisted to the top. This creates a problem because when the methods within those imported scripts are invoked they do not have access to the function within which they are invoked (Because they are inevitably defined outside those functions due to the hoisting issue). Therefore, I must always pass variables in an options object. Has anyone experiences a similar issue? Is there some sort of standard workaround that people use? Thanks!
function outer(){
//let's pretend we're in a node environment
//this required script will get hoisted to the very top and therefore lose access to the "something" variable!
var common = require('../globals/common.js');
var something = "something";
common.printsomething();//will return "something is not defined"
};
outer();
Hm.
I would assume that it'd ultimately be better to pass 'something' to the printsomething method, like so.
common.printfoo('bar'); //returns 'bar'
Typically, what you're doing there isn't how modules in node works. Yes, breaking up a large program into separate files is an excellent way to organize a project, but I'm afraid that I have to say you're doing it wrong here. In the context of 'outer', you could do:
/*script.js*/
var common = require('../globals/common.js');
function outer(str){
common.printsomething(str);//will return "something"
};
var something = 'something';
outer(something);
/*common.js*/
function printthing(str){
console.log(str);
}
module.exports = {
printsomething: function(str){
printthing(str)
}
}
module.js:
module.exports.print = function (data) {
console.log(data);
}
module.exports.add = function (a, b, callback) {
callback(a + b);
}
main.js
var mymodule = require('module');
module.print('Some data'); //Will print "Some data" in the console
module.add(25, 12, function (result) {
console.log(result); //Will print 37
});
As you can see, in main.js, I do not need to know the content of module.js to wrk. that is the goal of modules: put the hard logic somewhere else, to build better code. Modules like async or fs are huge and complex, but I just have to import them to work with it, and don't need to know how it does it.
While building your own module, think of it as a new library of tools, so that you can reuse it in another project without the need to set specific variables to use them. Imagine the chaos it would be if two module were able to get the content of your var something for unrelated goal!
Modules are self contained, to be reusable. A "de hoisting" of thoses would reduce their efficacity.
EDIT:
If you have a lot of environment variable, you can try a pattern where you set them once inside the module, but you have to make sure to provide a way to interact with them.
module:
var data = {};
function set(key, value) {
data[key] = value;
}
function get(key) {
return data[key];
}
function print(key) {
console.log(data[key]);
}
function add(keyA, keyB) {
return data[keyA] + data[keyB];
}
module.exports = {
set: set,
get: get,
print: print,
add: add
};
main.js
var mymod = require('mymod');
mymod.set('data', 'something');
mymod.set('a', 25);
mymod.set('b', 12);
mymod.print('data'); //Print "something"
var c = mymod.add('a', 'b');
console.log(c); //Print 32
I have module pattern done like this:
var A = (function(x) {
var methodA = function() { ... }
var methodB = function() { ... }
var methodC = function() { ... }
...
...
return {
methA: methodA,
methB: methodB
}
})(window)
This code let's me call only methA and methB() on A which is what I want and what I like. Now the problem I have - I want to unit test it with no pain ot at least with minimal efforts.
First I though I can simply return this but I was wrong. It returns window object.(can someone explain why?).
Second - I found solution somewhere online - to include this method inside my return block:
__exec: function() {
var re = /(\(\))$/,
args = [].slice.call(arguments),
name = args.shift(),
is_method = re.test(name),
name = name.replace(re, ''),
target = eval(name);
return is_method ? target.apply(this, args) : target;
}
This method let's me call the methods like this: A.__exec('methA', arguments);
It is almost what I want, but quite ugly. I would prefer A.test.methA() where test would never be used in production code - just for revealing private methods.
EDIT
I see people telling me to test the big thing instead of the small parts. Let me explain. In my opinion API should reveal only the needed methods not a bunch of internal functions. The internals because of their small size and limited functionality are much easier to test then test the whole thing and guess which part gone wrong.
While I may be wrong, I would still like to see how I could return references to all the methods from the object itself :).
Answer to your first question(you return this, but it returns window, not the object you wanted): in javascript this inside the function returns global object unless this function is a method of the object.
Consider next examples:
1) this points to the global object ():
function(){
return this;
}
2) this points to the object:
var obj = {
value: "foo",
getThisObject: function(){
return this;
}
}
Your case is example #1, because you have a function, that returns an object. This function is not a method of any object.
The best answer to your second question is to test only public methods, but if
that is so important for you, I can propose next:
create your modules dynamically on server side.
How it works:
create separate scripts for functionality you want;
create tests for these separate scripts;
create method that will combine scripts into one however you want;
to load script, reference to the combining scripts method.
Hopefully, it can solve your problem. Good luck!
Why not use namespaces to add your modules and public methods to js engine. Like this:
window['MyApp']['MODULE1'] = { "METHOD1" : {}, "METHOD2" : {}};
I write modules like this Sample module in JavaScript.
And test it like this: Simple unit testing in JavaScript
The use of eval() is generally not good idea.
I have a some JavaScript with a complex structure. Because I'm new comer to JavaScript (only understanding some basic concepts) I don't know how to use it properly.
I have two files : Circle.js and Line.js. In Circle.js, I want to use a class object defined in Line.js:
In file Circle.js :
Helper.using('py.Figures', function (ns) {
ns.Circle = function (params) {
// some additional methods and code here
}
}
And in Line.js is :
Helper.using('py.Figures', function (ns) {
ns.Line2Point = function (params) {
// some addition methods and code here
};
}
In Figures.Circle, in ns.Circle I want to use Line2Point but I don't know how.
I think it should be :
line = new ns.Line2Point(params);
But It seem doesn't work.
According to Helper Class, ns will point to helper.using, in this case py.Figures. Does it mean, ns is the same object/reference in both the files?
I don't think this is doable in Javascript directly across files. If they are part of the same namespace you could share some 'global' objects to achieve this have the line2points and circles attach themselves to that global object:
Ex:
var myShapesNameSpace = {};
Circle.js:
(function(){
var circle = {};
circle.method1 = function(){...}
circle.method2 = function(){...}
myShapesNameSpace.Circles = circle;
})(window.myShapesNameSpace = window.myShapesNameSpace || {}); //check if namespace object exists. Else create a new blank one.
Line.js:
(function(){
var line= {};
line.method1 = function(){...}
line.method2 = function(){...}
myShapesNameSpace.Lines= line;
})(window.myShapesNameSpace = window.myShapesNameSpace || {});
Now you can check for the existence of myShapesNameSpace.Circles or .Lines and call the corresponding methods accordingly.
You can include files in javascript and reference objects across files unless they are exported in some global form either via window or your define global
Welcome to Javascript, the shit parts. Require.js was designed precisely for this because the creators of JS, well, I guess thought that everyone would write every program in one file.
RequireJS
It was designed for web use but can be used elsewhere too (locally, with Node, etc.)
I have following structure for my client;
var myObject = (function(){
var mainObjectList = [];
var globalObject = {
init:function(mainObjectId){
var logger = {};
var utilityObject1 = {};
var utilityObject2 = {};
var mainObject = {};
mainObjectList.push(mainObject);
},//init
someOtherMethods:function(){}
};//globalObject
return globalObject;
})();
with my client I can say
myObject.init(5);
and create a new structure.
My problem is I have a lot of utility objects inside init function closure (logger, utilityObject1, utilityObject2..). My total file exceeded 1000 lines so I want to separate all utility objects into different files to have a better project. for example I could separate logger, utilityObject1 , utilityObject2 to their own files. the problem is since objects are in closure I cannot just add them to main object in separate files. so I thought of following injection method.
//start of file1
var myObject = (function(){
var mainObjectList = [];
var globalObject = {
init:function(mainObjectId){
var logger;
var utilityObject1 = {};
var utilityObject2 = {};
var mainObject = {};
mainObjectList.push(mainObject);
},//init
someOtherMethods:function(){},
injectLogger:function(creator){
this.logger = creator();
}
};//globalObject
return globalObject;
})();
//start of file2
myObject.injectLogger(function(){return {};});
That way I can separate my files for development. but in production I can concatenate files to have one file. But I have some problems with this design. I just added an accessible injectLogger function into myObject. and my logger cannot use other local variables in closure now(I have to pass them to creator object now). My question is is there any other way to separate that kind of code into files. (maybe an external utility.)
I like to use google's closure compiler http://code.google.com/closure/compiler/
If you don't want to use something like that, you might try this sort of thing: (Make sure you load globalObject.js first to define the variable).
//globalObject.js
var globalObject = function() {
}
//init.js
globalObject.prototype.init = function() {
this.utilityFunction();
//do something with utilityObject1
this.utilityFunction(this.utilityObject1);
}
//utilityFunction.js
globalObject.prototype.utilityFunction= function() {}
//utilityObject1.js
globalObject.prototype.utilityObject1 = {};
//main.js
var myObject = new globalObject();
myObject.init();
You could then overwrite the function by doing something like this:
//main.js
var myObject = new globalObject();
myObject.utilityFunction = function() {
//new function
}
myObject.init(); // This will then use the new utilityFunction method you just set.
As I understand it, you want to have some lexical variables that all of your modules close over, but you want to keep the code for the various modules in different files.
One way to achieve this exact behavior is to create a single Javascript file by concatenating the module definitions together:
Header.js-partial
var myObject = (function(){
var mainObjectList = [];
var globalObject = {
init:function(mainObjectId){
Logger.js:
function Logger() { this.enabled = true; }
Logger.prototype.log = function() {
if (window.console && window.console.log) {
return window.console.log.apply(window.console.log, arguments]);
}
}
etc.
Add other module files as desired. They can reference lexical variables.
Footer.js-partial
}// end init
}; // end globalObject
return globalObject;
})();
In the end you need a script that will concatenate all of these files together into a single js file. There is no other way to get truly lexical variable access in pure Javascript.
A superior alternative
That said, this technique is ripe for confusion and I don't recommend it. Closures are generally meant for closing over local variables, not program-wide variables. If you use a lexical variables declared 1000 lines ago, you will spend some amount of time tracking down where all your variables were declared when running your program. Instead you should probably enclose private, 'global' data in the globalObject. For example, store mainObjectList in globalObject.mainObjectList and reference that in module files.
I recommend a solution like that described by nemophrost. Each file should be valid javascript on its own.
You could use command-line PHP to serve as a preprocessor to combine your files. For example, main.js.php could look like this:
(function() {
<?php require('foo.js.php');?>
})();
and then run the command php main.js.php > combined.js when you want to produce an output file usable for minification and deployment.
This has the advantage that you can load main.js.php onto a server to test a new version of the code without recompiling. You can just put a line at the very beginning of main.js.php to get PHP to send the correct MIME type:
<?php header('Content-type: text/javascript');?>
The way I deal with this problem to check to see if the global object exists and if not create it. This way the order isn't important.
// file 1
var Global_Obj = Global_Obj || {}; // creates empty global object
Global_Obj.An_Obj = { /* stuff */ };
// file 2
var Global_Obj = Global_Obj || {}; // uses created global object
Global_Obj.Another_Obj = { /* stuff */ };
Given a namespaces ns used in two different files:
abc.js
ns = ns || (function () {
foo = function() { ... };
return {
abc : foo
};
}());
def.js
// is this correct?
ns = ns || {}
ns.def = ns.def || (function () {
defoo = function () { ... };
return {
deFoo: defoo
};
}());
Is this the proper way to add def to the ns to a namespace? In other words, how does one merge two contributions to a namespace in javascript?
If abc.js comes before def.js I'd expect this to work. If def.js comes before abc.js I'd expect ns.abc to not exist because ns is defined at the time.
It seems there ought to be a design pattern to eliminate any uncertainty of doing inclusions with the javascript namespace pattern.
I'd appreciate thoughts and input on how best to go about this sort of 'inclusion'.
Thanks for reading.
Brian
That would certainly work. Keep in mind, though, that source order will affect your implementation: if def.js ever winds up included before abc.js, your definition of foo and ns.abc will never be executed.
Take a look at YUI's old namespace function for an example: they make sure either use the existing object or a new object initialization, probably for that reason above.
It might very well help you to keep your modules separate with something like this:
ns = ns || {};
ns.abc = function(){ ... }();
and
ns = ns || {};
ns.def = function() ... }();
That way, each is a separate module, source order doesn't matter, and each has access to its own closure as you have in your example.
As a matter of interest, I discovered AMD and RequireJS and started using that.