Objects within Exports Object - javascript

So I've been looking at this post: What is the purpose of Node.js module.exports and how do you use it? and have been trying to make sense of it within the scope of JavaScript objects.
So if I have this in game.js:
var myObj = function() {
this.function1 = function(){
...
};
};
exports.myObj = myObj;
In the other file I'm assuming that I would do something like this:
var RequiredObj = require('game.js');
or
var RequiredObj = require('game.js').myObj;
Where I get lost is how to then use this object and its function, also how to create a new instance of this object.
Would it be something like this?
RequiredObj.myObj.function1();
and
RequiredObj.myObj = new RequiredObj.myObj();
Also is there any limit to how big the object I'm passing is? Because in my actual script my game object is huge.

Assuming the "other file" is in the same directory as game.js, something like this should work:
var game = require('./game.js');
var mo = new game.myObj();
mo.function1();
A few things to note:
Modules within your project should be specified with a path -- leading with ./, ../, or /. Otherwise, require will only search for the module as a core module or in node_modules folders (e.g., via npm install).
myObj appears to be a constructor and function1 would be an instance method. So, RequiredObj.myObj.function1() will error as no instance is created.
On the other hand, RequiredObj.myObj = new RequiredObj.myObj() should work... once. This line sets over the reference to the constructor with a reference to an instance, rendering the constructor (mostly) inaccessible. ("Mostly" because it can still be available as RequiredObj.myObj.constructor, but declaring a new variable for the instance is generally simpler.)
Also is there any limit to how big the object I'm passing is?
ECMAScript doesn't define any explicit limits on the size of an Object. Though, you'll of course be limited by the hardware used to execute the application.

Related

What is the node-way to talk about require, import, and packages?

I have two files in my javascript project:
app.js
require('sugar')
var Notification = require('./notification');
let createdOn = 'now'
let notifyOn = 'in 2 days'
let someNotification = new Notification('go somewhere', Date.create(createdOn), Date.create(notifyOn))
someNotification.print()
notification.js
function Notification(content, createdOn, notifyOn) {
this.content = content
this.createdOn = createdOn
this.notifyOn = notifyOn
}
Notification.prototype.print = function() {
console.log('content', this.content)
console.log('createdOn', this.createdOn)
console.log('notifyOn', this.notifyOn)
}
module.exports = Notification
in notification.js I think I'm "writing my own module" that "exports a constructor" to whatever requires it. Then in app.js I "import my the Notification module" which is in the same working directory as app.js. I also "import the Sugar package" so I can convert natural language into a DateTime see Sugar.js for details about that.
Next I'm "creating an instance of Notification" and calling one of it's "instance methods".
I'm wondering: what is the node-way for saying everything above, especially the parts in quotes? Specifically I'm confused about how to speak precisely about a constructor, and prototype functions, and what the difference is between these two lines:
require('sugar')
var Notification = require('./notification');
I'm looking for an answer that, using node idioms, explains to me what I did in my project.
Thanks
😄
There is no documented, standard node idiom-speak. Your explanation is pretty much what you are doing in terms that any node developer would understand. Here's the shortest node-phrasing I can think of:
require('sugar')
load the sugar module
var Notification = require('./notification');
load the notification module from the current module's directory and assign the exports to a variable named Notification
notification.js
A module that exports a constructor function for creating Notification objects.
what the difference is between these two lines:
require('sugar')
var Notification = require('./notification');
The sugar module can be used without assigning its exports to any variable because the main thing it does is add methods to the existing Date and Number prototype (commonly referred to as "extending an existing object") and you use many of its features by accessing methods like Date.create() that it added.
So, its functionality is added to objects that already exist and that's how you use its functionality. This is not particularly common - I'm not aware of any specific name for a module that loads this way.
Next I'm "creating an instance of Notification" and calling one of
its "instance methods".
That is already a node-way to say it.

use `module` as namespace

I've been using a pattern in my node.js modules that seems so obvious to me that I assume there must be something wrong with it or I would see more people doing it. To keep private variables that are global to the module, I simply attach them as properties on the module object. Like so:
module.exports = {
init: function() {
module.someClient = initializeSomethingHere()
},
someMethod: function(done) {
module.someClient.doSomething(done)
}
}
This seems preferable to me than something like this...
var someClient;
module.exports = {
init: function() {
someClient = initializeSomethingHere()
},
someMethod: function(done) {
someClient.doSomething(done)
}
}
...because in the second example you need to go searching for var someClient at the top of the file to make sure that the omission of the var keyword is intentional within the init method. I've never seen this pattern used elsewhere though, so I wonder if I'm missing something that makes it less than ideal.
Thoughts?
There are a couple of possible downsides that come to mind.
1) It's technically possible for those properties to be accessed and modified outside the module, but only if a reference to the module itself is available outside it. Something that makes the module available through its own exports (module.exports = module; being the simplest example) would expose them.
2) You could have a naming conflict with a builtin property or a future builtin property that doesn't exist yet (which would cause your code to break in future versions of node.js). This could be very problematic and very hard to debug. Currently the built-in properties on a module object are: children, exports, filename, id, loaded, paths, and parent.
because in the second example you need to go searching for var someClient at the top of the file to make sure that the omission of the var keyword is intentional within the init method.
If that is the reason, you could just use a namespace that isn't module. For instance by adding var private = {}; to the top of each file and then using private.someClient instead of module.someClient.
Also 'use strict'; so that the accidental omission of var is an error and not an accidental global.
Drawbacks
Option 1: This practice is prone to naming conflict with a builtin property or a future builtin property that doesn't exist yet, as #paulpro stated in his answer.
Option 2: If you miss var keyword and expose the someClient globally. Besides you need to go searching for var someClient at the top of the file all the time.
Alternative
As JavaScript has function scope it's better to define everything within a function. Creating private and public members within a function. Below is a design pattern which one can follow:
'use strict';
module.exports = (function(){
//private
var someClient;
//public properties
var that={};
that.init = function() {
someClient = initializeSomethingHere()
},
that.someMethod: function(done) {
someClient.doSomething(done)
}
//expose only the required methods
return that;
})();
Here only exposed methods are those which are attached to that object. And all rest are private to the function scope. Even if you miss the var keyword in someClient it won't be accessible out side of the function, which won't ever happen if you use 'use strict' at the top.
Logic is first time when you require the xyz.js file it will return the that object rather than the function.

js - avoiding namespace conflict

Thus far I've worked only with relatively small projects (and mostly alone), but this time I have to collaborate with other programmers... basically because of that I must plan the structure of the website very carefully for the avoidance of spending hours debugging the code.
At this point I suppose doing that in the following manner. I divide my code in modules and store each module in a separate file inside an object (or a function) with a made-up name (lzheA, lzheB, lzheC etc.) to avoid conflicts whether an object with the same name was used in an another piece of code. When the document is loaded, I declare a variable (an object) that I use as a main namespace of the application. Properties of the object are the modules I defined before.
// file BI.lib.js
var lzheA = {
foo: function() {
},
bar: function() {
},
}
// file BI.init.js
function lzheK() {
BI.loadPage();
}
// file BI.loadPage.js
function lzheC() {
var result = document.getElementById('result');
result.innerHTML = "that worked";
}
// and so on
var lzheA,lzheB,lzheD,lzheE,lzheF,lzheG,lzheH,lzheI,lzheJ;
// doing the following when the document is loaded
var BI = {
lib: lzheA,
menu: lzheB,
loadPage: lzheC,
customScripts: lzheD,
_index: lzheE,
_briefs: lzheF,
_shop: lzheG,
_cases: lzheH,
_blog: lzheI,
_contacts: lzheJ,
init: lzheK,
}
BI.init();
https://jsfiddle.net/vwc2og57/2/
The question... is this way of structuring worth living or did I miss something because of lack of experience? Would the made-up names of the modules confuse you regardless of the fact that each one used only twice - while declaring the variable and assigning it to a property?
I consider the namespaces a good option when you want to modularize applications in Javascript. But I declare them in a different way
var myModule = myModule || {}; // This will allow to use the module in other places, declaring more than one specificComponent in other js file for example
myModule.specificComponent = (function(){
// Private things
var myVar = {};
var init = function() {
// Code
};
return {
init: init // Public Stuff
};
})();
If you want to call the init method, you would call it like this
myModule.specificComponent.init();
With this approach, i guarantee that the module will not be overwritten by another declaration in another place, and also I can declare internal components into my namespaces.
Also, the trick of just exposing what you want inside the return block, will make your component safer and you will be encapsulating your code in a pretty way.
Hope it helps

why does this object declaration work in node.js and how to declare a static variable?

i have seen this code :
var myNet = require ("net");
and in some function:
function foo (x,y) {
var myNewNet = new myNet();
myNewNet.createServer(x,y);
}
why does the code above create a new object? what is the mechanism stands behind that?
one more question, how do i create a static var in node.js, for example a id number that has to be unique.
i came with this option for static variable:
var id =0;
and put it on the global scope, is it ok?
The require statement basically is like an import; it takes an external library and makes it available in your code.
If you ever look in an external module, you will notice that it's just normal node.js js code. It has EXPORT statements in it. Those statements are what gets made available when you require something. Check out http://howtonode.org/creating-custom-modules
There is a GLOBAL keyword in node.js you can use to make something global
GLOBAL.IP_ADDRESS = "..."
As #Raynos says, it's not usually a good idea to do that, so another options is to export a constant from a module, so you can create a module and do
exports.STATIC_CONSTANT = "";
and then once you import the module you can do
var mod = require('mymodule');
mod.STATIC_CONSTANT;
EDIT, to answer you comment, the line
var myNet = require("net")
causes myNet to be whatever the net module exports. It must be exporting a function, so
var newNet = new myNet()
creates a new instance of the net object. From there
myNewNet.createServer()
is just invoking a method on the object you just created.

simple Constructor Pattern

I have worked with oop style scripting before and trying to get some kind of system with javascript. I wanted to try the most basic pattern, Constructor Pattern.
So I setup one js file called ImageView with a constructor matching the name of the js file.
function ImageView(){
alert( 'this is working');
}
Then I set up another js file called Main.js which will be the main instantiation class.
$(document).ready(function(){
var imageViewer = new ImageView();
//ImageView();
});
Now what I don't get is I can call this object ImageView without even the new constructor call. For example ImageView(). From what I gather this is just another global function and not a encapsulated class. I'm trying to get away from global crap and separate my methods and properties to their own class. What am I missing her.
Others have already answered what the difference is between using new and not using it, so I'll answer your entirely separate question: how do I avoid globals in JS?
The answer is that you can't entirely. You will always have at least one, in which you can stuff your other stuff. So for example if you wanted a "namespace" of xyz, you would do:
// global:
var xyz = {}; // or, window.xyz = {} if you are in a browser and want to be more explicit.
// "encapsulated" within the xyz "namespace":
xyz.ImageView = function () { alert("This is working"); };
There is a better solution: use the emerging concept of JavaScript modules. These are not language features (at least not in the current version of JavaScript), so they are really just hacks introduced by very clever libraries that overwrite a couple of global variables to let you avoid creating any more than the ones provided by those libraries. A good example is RequireJS, where you could do something like the following:
// In xyz.js, define the xyz module (name automatically derived from filename).
// Whatever is returned from the function you pass to define is "the xyz module"
define(function () {
return {
ImageView: function () { alert("This is working"); }
};
});
// In other code, in a different file, you can say "I require the xyz module
// to do my work," and pass require a function saying "once you've got the xyz module
// for me, here's the work I will do with it".
require(["xyz"], function (xyz) { // dependency array maps to callback arguments
// I got the xyz module, including the ImageView function it exported. Use it!
var imageViewer = new xyz.ImageView();
});
Here the clever globals RequireJS introduces are the functions define and require, but if you use them right, you can avoid ever introducing any further globals beside those two.
Inside of ImageView, the value of this will be different if you call it with new. Without, it's just another function. With new it will create a new ImageView instance and bind it to the variable this.
First off JavaScript doesn't have built in namespaces. It can only be simulated. You must also include each javascript file you plan on using.
Your right about just calling ImageView() that basically invokes the constructor on this which is next level of scope.
Using new ImageView() creates a new Object of constructor ImageView and this points to the new instance.
JavaScript is a prototype language with loose typing.

Categories