Okay, experimenting with CommonJS module system in the context of NodeJS.
module.exports = pricingCalculator;
function pricingCalculator (options) {
var target = {};
return target;
}
This works. Presumably the variable declaration of pricingCalculator is hoisted to the top of the function scope, so the misordering doesnt quite matter as the function is passed by reference anyway. I get that. What I dont understand is why the following two versions that work:
module.exports = pricingCalculator;
var pricingCalculator = function (options) {
var target = {};
return target;
}
Fail.
module.exports = pricingCalculator;
pricingCalculator = function (options) {
var target = {};
return target;
}
Fail. Curious to understand deeply what is going on.
In first example function is defined before assignment (java script way).
In second and third examples assignments are executed in sequence.
http://studiokoi.com/blog/article/execution_order_of_functions_and_variables_in_javascript_and_actionscript
Related
This question may contain answer, I was thinking about possible solutions to that. However, I would like to know, if (and how) someone had done it in better way.
The problem is, that I have really long function constructors and the whole instance of that function contains lot of properties and so I try to 'initialize' these properties on the very beggining of the function constructor, because I would like to exactly know, what is used and assure myself, that there are no new declaration of properties somewhere in the middle of the code.
I know, that it is quite simple, when we think about 'normal' variables, when we "use strict":
"use strict"
favouriteAnimal = 'honeybadger'; //Uncaught ReferenceError: favouriteAnimal is not defined
This will throw and Error, because we haven't used:
"use strict"
const favouriteAnimal = 'porcupine';
or
"use strict"
var favouriteAnimal = null //or let
favouriteAnimal = 'aardvark';
In these following scenarios, please notice the 'this.importantFunction' and 'this.favouriteAnimal'. The rest of constructor function only demonstrates slightly complicated object structure, which would benefit from such early variable (property) definition.
But the struggle beggins within Objects, in following scenario, this is what is typically done, it is working, but it does not offer such safety precautions as to force us defining all variables first.
function TypicalContructorFunction1 ()
{
this.someRandomFunctionWithoutRealPurpose = function () {
console.warn('someone really used me?');
}
this.someStuff = 'coffee break';
this.differentStuff = 'broken coffee';
this.importantFunction = function (animalName) {
this.favouriteAnimal = animalName;
};
this.importantFunction('sewer rat');
return this;
};
var typicalObject1 = new TypicalContructorFunction1();
console.log(typicalObject1.favouriteAnimal)
Console will log an Object with property 'favouriteAnimal', but as the object structure is slightly fatter and so it is not clearly visible, that such property was defined.
Another approach with 'helping' function:
function useProperty (object, propertyName, closure) {
if (object && typeof object[propertyName] !== 'undefined') {
closure(object[propertyName], object, propertyName);
} else {
throw new ReferenceError('property "' + propertyName + '" not declared');
}
};
const TypicalContructorFunction2 = function ()
{
this.someRandomFunctionWithoutRealPurpose = function () {
console.warn('someone really used me?');
}
this.someStuff = 'coffee break';
this.differentStuff = 'broken coffee';
this.importantFunction = function (animalName) {
useProperty(this, 'favouriteAnimal', function (property)
{
property = animalName;
});
};
this.importantFunction('drosophila melanogaster');
return this;
};
var typicalObject2 = new TypicalContructorFunction2();
There is no need for console.log, because new ReferenceError will be thrown and execution stopped, which is what I want. However, this calling a function, passing a function to just change a simple value seems a bit as overkilling and I think, that it may have performance drawbacks too.
And as last (but not least) I came up with sealing the object after declaring all properties, so there cannot be added any other properties. (needs "use strict")
"use strict"
function TypicalContructorFunction3 ()
{
this.someStuff = null;
this.differentStuff = null;
this.someRandomFunctionWithoutRealPurpose = null;
this.importantFunction = null;
Object.seal(this);
this.someRandomFunctionWithoutRealPurpose = function () {
console.warn('someone really used me?');
}
this.someStuff = 'coffee break';
this.differentStuff = 'broken coffee';
this.importantFunction = function (animalName) {
this.favouriteAnimal = animalName;
};
this.importantFunction('jerboa');
return this;
};
var test = new TypicalContructorFunction3();
ReferenceError: property "favouriteAnimal" not declared
I think, that this may be the answer, while it does not seal the object deeply (there would definitely be some code snippets with deep sealing on StackOverflow).
I also know, that I can still use var/const/let inside function, but such variables become private and cannot be accessed from outside of the function.
Have you come up with different solutions to this issue?
PS: Please, this answer is asked for ECMAScript v5, as it is in the title.
Thanks for ideas :)
I've got an extremely small ES6 code:
var name = "MyName";
var version = "1.2.3";
var theThing = {
name,
version,
run: () => {
console.log(`You're using ${this.name}#${this.version}`);
}
};
theThing.run();
When I run it inside the browser console (chrome 53), I get the expected result: You're using MyName#1.2.3 is logged to the console. Both template strings work along with shortened object literal syntax.
However, when I try to use gulp/babel to transpile this code down to ES5, using the most basic setup (taken from here):
const gulp = require('gulp');
const babel = require('gulp-babel');
gulp.task('default', () => {
return gulp.src('src/app.js')
.pipe(babel({
presets: ['es2015']
}))
.pipe(gulp.dest('dist'));
});
I get following output:
"use strict";
var name = "MyName";
var version = "1.2.3";
var theThing = {
name: name,
version: version,
run: function run() {
console.log("You're using " + undefined.name + "#" + undefined.version);
}
};
theThing.run();
As you can see, it's calling undefined.name instead of this.name, I've got absolutely no idea why is this replaced with undefined. Of course, this code doesn't work as expected:
VM329:8 Uncaught TypeError: Cannot read property 'name' of undefined(…)
and is not ES6 compliant (original implementation of ES6 in chrome53 works correctly).
You can also see this issue in the Babel REPL.
Am I doing something wrong - or is it a bug in babel?
in your original source try to replace
var theThing = {
name,
version,
run: () => {
console.log(`You're using ${this.name}#${this.version}`);
}
};
by
var theThing = {
name,
version,
run: function () {
console.log(`You're using ${this.name}#${this.version}`);
}
};
The arrow syntax function changes the way this works
Arrow functions don't bind to this (see here). Therefore when you define the function, the object doesn't yet exist... so Babel doesn't know about the context.
Getting rid of the arrow function will fix it.
The arrow function this points to window because of the lexical binding. When you call theThing.run(), you actually get window.name, and window.version in the template. If you rename the the global variables it won't work:
var n = "MyName";
var v = "1.2.3";
var theThing = {
name: n,
version: v,
run: () => {
console.log(`You're using ${this.name}#${this.version}`);
}
};
theThing.run();
To solve that, don't use the arrow function:
var n = "MyName";
var v = "1.2.3";
var theThing = {
name: n,
version: v,
run() {
console.log(`You're using ${this.name}#${this.version}`);
}
};
theThing.run();
The proper answer consists of 2 points:
arrow functions and classical ES5 functions have completely different this binding. this in classical functions is very dynamic (determined in runtime, no matter where is it defined), whereas in arrows, it's lexically bound (bound in where it's placed, runtime has no affect on that, runtime is already too late to change it). Lexical scope makes an arrow function borrow this from the closest enclosing classical function, if present. If not present, it's taken from global scope...
if not in strict mode, window is taken. If in strict mode, undefined is taken
... which precisely answers above question.
So the first one being something like:
myFile.js
var name = "Peter";
module.exports.sayHello = function () {
console.log('Hello ' + name);
}
And the second one
myFile.js
module.exports = function () {
var name = 'Mary';
function sayHello () {
console.log('Hello ' + name);
}
return {
sayHello : sayHello
};
}();
Essentially it's the same thing right? If not, what's the difference and what's the pros and cons of each method?
Why do we need modules?
When you have a code like this:
// module 1
var a = 1;
var x = function (){
return a;
};
// module 2
var a = 2; // duplicated variable declaration
var y = function (){
return a;
};
// main
console.log(x()); // BUG: this should read value from module 1 instead of module 2
console.log(y());
It will lead to error, since the a variable was already taken by the first module. You need to define modules somehow.
Using a prefix
By old-style procedural programming you would add a prefix to separate modules:
// module 1
var m1_a = 1;
var m1_x = function (){
return m1_a;
};
// module 2
var m2_a = 2;
var m2_y = function (){
return m2_a;
};
// main
console.log(m1_x());
console.log(m2_y());
But this makes the code less readable.
Using closures
By javascript you have closures, which make things a little bit easier:
// module 1
var x = (function (){
var a = 1;
var x = function (){
return a;
};
return x;
})();
// module 2
var y = (function (){
var a = 2;
var y = function (){
return a;
};
return y;
})();
// main
console.log(x());
console.log(y());
But still you have different modules in a single file, so that file will be really big and hard to maintain.
Using the node.js module loader
By node.js you can move the code of different modules to separate files, so it will be easy to maintain the code of different modules, since you will be able to find the relevant part of the code much faster:
m1.js
var a = 1;
var x = function (){
return a;
};
module.exports = x;
m2.js
var a = 2;
var y = function (){
return a;
};
module.exports = y;
main.js
var x = require("m1");
var y = require("m2");
console.log(x());
console.log(y());
You can do the same in the browser
The simplest node.js style browser module loader I could come up with so far, is this:
var cache = {};
function require(name){
if (name in cache)
return cache[name];
var uri = "./" + name + ".js";
var xhr = new XMLHttpRequest();
xhr.open("GET", uri, false);
xhr.send(null);
var moduleCode = xhr.responseText;
var fn = new Function("module", moduleCode);
var module = {};
fn(module);
cache[name] = module.exports;
return cache[name];
};
Ofc. it is much safer to use browserify, webpack, require.js and other more sophisticated libs, I just wanted to show you, it is not that hard to write a loader.
What did we learn from all of this?
Both node.js modules and closures are for modularization. You should not mix them, since they solve the same problem, and mixing them will lead only to confusion!
For me it's the same thing.
Maybe the first example is more common.
You can use both, according to the rest of your code.
Yes they are basically the same. You just don't need the verbosity of the second example.
In the first example you are adding a named property to the already existing module.exports object injected by node.js, in the second example you are overriding the original object - there is no difference for the consuming end.
Lets go to the basics of module mechanism in NodeJS. For every JS
file the ground reality is which happens on the top of file:
var exports = module.exports = {};
Whenever we try to fetch the import it retrieves module.exports only
If we do both in Js file
exports.key = "key1" and module.exports = {key : "VAL"}
only the module.exports is fetched during the import according to the rule.
Now coming back to your question Adding module.exports.sayHello will
add the reference to the {} which is common with exports variable too.
However if you do
module.exports = function () {} // some function
it breaks the chain and it is only assigned to module.exports and not
exports variable.
This is why if we add any key to exports variable is retrieved via
module.exports during import! Hope it clarifies!
A very good article on this https://www.sitepoint.com/understanding-module-exports-exports-node-js/
In want to define a function-constructor inside a namespace. The way in which I defined the constructor till now was a simple constructor function without NS, combined with prototypal inheritance.
The code looked kind of like:
function mySuperObject() {
var self = this;
self.p1 = "";
self.p2 = "jkejie";
// and others
}
mySuperObject.prototype.func1 = function(){...}
// and others
Introducing namespace:
After reading many articles I decided to start up with a very simple way to define a namespace, maybe the most simplest.
Basically it is just about defining a variable which points to an object-literal and the content is the object (the "mySuperObject" in the code-snippet above). The constructor function is following: mySuperObjectInNS.
The code of the object:
var MYNAMESPACE = {
//some variable outside the object
file : "ConstructorInNamespace_obj.js: ",
//Defining contructor function inside a namespace
mySuperObjectInNS : function(propOne, propTwo){
var self = this;
self.objectName = "mySuperObject";
self.propertyOne = propOne;
self.propertyTwo = propTwo;
self.doSomething = function(){
console.log(file + " doSomething called - function of object");
};
///many more functions and attributes
}
}
MYNAMESPACE.mySuperObjectInNS.prototype.specialFunction = function(){
console.log(file + " specialFunction called - prototypical inheritance defined in file of object, outside of namespace");
};
///many more functions and attributes
In another file it is possible to intantiate the object, as follows:
...
var objOne = new MYNAMESPACE.mySuperObjectInNS("param11", "40");
//following line works just fine
objOne.doSomething();
....
Questions:
It seems to me that this all is about defining an Object-Literal and
I will come into trouble the latest I am trying to define "private"
properties of that object. Is this correct?
Is that mySuperObjectInNS still a constructor function? (For me it
seems it is something else,even if I can intantiate objects from it.
Is is a very bad very bad way of namespacing or is kind of ok?
It seems to me that this all is about defining an Object-Literal and I will come into trouble the latest I am trying to define "private" properties of that object. Is this correct?
"Private properties" have nothing to do with using an object for namespacing. In fact, originally when answering this question, I read that as "private functions" because that would be relevant.
There are lots of ways to do private and semi-private properties in JavaScript, but they relate to how you create the constructor function and the methods it gives the object, not how you expose the constructor function. "Namespace" objects are about how you expose the constructor.
One common pattern for creating "private" properties is to define methods that need to access them within the constructor, and make the "properties" local variables within the constructor (so they aren't really properties at all), like this:
function SuperObject() {
var privateInformation;
this.method = function() {
// This can access `privateInformation`, which is completely
// hidden from outside the constructor
};
}
It doesn't matter at all if you do that within a "namespacing" pattern or on its own.
Private functions, on the other hand, affect the pattern. I'll show both below.
A fairly common variant that provides for private functions is to use a function to create the object, which also gives you the opportunity to create private functions:
var TheNamespace = function() {
function privateFunction() {
}
function SuperObject() {
var privateInformation;
this.method = function() {
// This can access `privateInformation`, which is completely
// hidden from outside the constructor
};
}
SuperObject.prototype.otherMethod = function() {
// Can't access `privateInformation`, but has the advantage
// that the function is shared between instances
};
return {
SuperObject: SuperObject
};
}();
// usage
var s = new TheNamespace.SuperObject();
Is that mySuperObjectInNS still a constructor function? (For me it seems it is something else,even if I can intantiate objects from it.
Yes. A constructor function is any function that expect you to use new with it.
Is is a very bad very bad way of namespacing or is kind of ok?
Using objects as pseudo-namespaces is common practice. You might also consider various asynchronous module definition (AMD) technologies, which largely make "namespace" objects largely unnecessary.
Re your comment:
You defined a self-invoking function....which returns an an object?
It's not a self-invoking function, it's an inline-invoked function, but yes, it's a function that returns an object.
(if so I think parantheses are missing)
No, we don't need any parens that aren't there because the only reason for the outer parens other places you've seen this are to tell the parser that the word function starts an expression rather than declaration; we don't need that in the above because we're already on the right-hand side of an assignment, so there's no ambiguity when function is encountered.
Due to you proposed this way, is it a better way to define the ns?
"Better" is a subjective term. It gives you a scope in which you can define private functions, which you'd asked about.
Whereas I often also saw the option: var = {} | someNSName; What is this all about?
If you have several files that will add things to the "namespace" (as is common), then you frequently see this in each of them:
var TheNamespace = TheNamespace || {};
What that does is declare the variable if it hasn't been declared before, and assign an empty object to it if it doesn't already have one. In the first file that gets loaded, this happens:
The var is processed and creates a new variable, TheNamespace, with the value undefined.
The TheNameSpace = TheNameSpace || {} assignment is processed: Since undefined is falsey, the curiously-powerful || operator results in the new {}, which gets assigned to TheNamespace.
When the next file loads, this happens:
The var is a no-op, because the variable already exists.
The TheNameSpace = TheNameSpace || {} assignment is processed: Since TheNamespace has a non-null object reference, it's truthy, and the curiously-powerful || operator results in a reference to the object TheNamespace refers to.
That is, it has no effect at all.
This is used so you can load the files in any order, or load just one file in isolation.
Here's an example:
thingy.js:
var TheNamespace = TheNamespace || {};
TheNamespace.Nifty = function() {
function privateFunction() {
}
function Nifty() {
var privateInformation;
this.method = function() {
// Can access `privateInformation` here
};
}
Nifty.prototype.otherMethod = function() {
// ...
};
return Nifty;
}();
thingy.js:
var TheNamespace = TheNamespace || {};
TheNamespace.Thingy = function() {
function privateFunction() {
}
function Thingy() {
var privateInformation;
this.method = function() {
// Can access `privateInformation` here
};
}
Thingy.prototype.otherMethod = function() {
// ...
};
return Thingy;
}();
There are lots of variations on that basic pattern, particularly if one file may add multiple things to TheNamespace. Here's one that supports doing so fairly concisely:
var TheNamespace = function(exports) {
function privateFunction() {
}
function Nifty() {
var privateInformation;
this.method = function() {
// Can access `privateInformation` here
};
}
Nifty.prototype.otherMethod = function() {
// ...
};
exports.Nifty = Nifty;
function Thingy() {
var privateInformation;
this.method = function() {
// Can access `privateInformation` here
};
}
Thingy.prototype.otherMethod = function() {
// ...
};
exports.Thingy = Thingy;
}(TheNamespace || {});
I am currently writing all javascript functionality of a certain page in JQuery's document.ready handler:
$(document).ready(function() {
var one, two, three;
function f1(par1) {}
function f2() {}
...
});
I feel that this isn't optimal or according to Javascript best practices. What I need is a private scope for the page's functionality, nothing needs to be called externally.
I've seen a number of different ways:
jQuery source
(function(window) {
var anObj = {};
...
window.functionality = anObj;
}(window));
A function that is self-invoked with the window as parameter, then setting the functionality object of your application on it.
Codemirror source
window.functionality = (function() {
var functionality = {};
...
return functionality;
}());
Very similar to what jQuery does, but setting the functionality object indirectly on window by making a self-invoking function return something first.
This question
var functionality = {};
(function(obj) { obj.f1 = ... }(functionality));
Creating a local variable (instead of on window), and setting its content inside a self-invoked function (why?)
How do I declare a namespace in JavaScript?
var functionality = {
f1: function(){},
f2: function(){}
}
Pretty much the same as the previous thing but setting the contents without a self-invoking function (again why use or not use the self invoking function?).
So... which way is best?
I would suggest the module pattern for this, where a page is treated as a module. There is a lot of information about the javascript module pattern on the web. Have a look at http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html.
I've used an example from the link and modified it a bit:
var MyApp = MyApp || {};
MyApp.PageX = (function () {
var my = {},
privateVariable = 1;
function privateMethod() {
// ...
}
my.moduleProperty = 1;
my.moduleMethod = function () {
// ...
};
return my;
}());
What is happening here, is that a set of properties and methods is defined and namespaced to MyApp.PageX, MyApp being the global. So this will work:
MyApp.PageX.moduleProperty; // 1
MyApp.PageX.moduleMethod();