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.
Related
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.
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
I'm fairly new to node.js, prototypical inheritance and the CommonJS module patterns.
Maybe this question was answered a million times, but I couldn't find it, so even a link to the answer is considered an answer.
I have to wrap a module that has both named and unnamed functions, like this:
// a.js
function a(data) {
console.log(data, 'A')
}
function b() {
a('B');
}
module.exports = a;
module.exports.b = b;
Given OOP background I would like to somehow 'inherit' all the functions of the module while I want to override the anonymous function (I'd like to add some fields to the data).
It is very important that after overriding function a in the new module function b should use the overridden method and not the original one.
// 'inherited.js'
var a = require('./a');
function overriddenA(data) {
data.myAddedValue = 'an important addition';
a(data);
}
// I would like to export all other functions and properties of the original module
[magic that overrides the anonymous function while keeping all other functions as they are]
From where I use it should look like this:
var decoratedA = require('./inherited');
decoratedA('stuff'); // it calls overridden function
decoratedA.b(); // it calls the original a.b() which in turn calls the overridden function
Solved our original problem
Check out this: https://stackoverflow.com/a/31459267/2018771 - still if you have any comment on the abstract problem, please answer the question. We are curious :).
I would like to somehow 'inherit' all the functions of the module while I want to override the anonymous function
Wanna use some dark magic? Then __proto__ is the way to go:
var a = require('./a');
function overriddenA(data) {
data.myAddedValue = 'an important addition';
a(data);
}
overriddenA.__proto__ = a;
module.exports = overriddenA;
The cleaner method, without actual inheritance, would be to just copy over all properties from a to overriddenA. You can use Object.assign (or a shim), _.extend, or a simple for in loop for that.
Meanwhile we have solved our original problem which was adding a special header to every calls of request library. In that implementation there were functions like get(), put(), post(), etc. that used one function: function request(...) which was exported module.exports = request
My understanding was that I had to replace that request(...) with our own, adding our header and then calling the original function.
But we were lucky because request(...) returned an object which we could modify according our needs:
Request.prototype.__originalInit = Request.prototype.init;
requestPromise.Request.prototype.init = function(options){
console.log('adding our stuff');
this.__originalInit(options);
};
So this solved the problem for us, but not the original question.
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.
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.