Module pattern - separation of concerns - encapsulation in ES6 - javascript

I am about to rewrite an app (it is in vanilla JS originally) in ES6, in which module patter is apllied.
In no time, at the beginning I realized that I am struggling to get 'separation of concerns' done since if we are about to apply data privacy in ES6 we only use "{}" but not IIFE's as in case of vanilla JS (which as known are practically function expressions).
Vanilla JS solution:
var budgetController = (function() {
const x = 20;
function add(a) {
return x + a;
}
return {
getSum: function(b){
console.log(add(b));
}
}
})();
UIController = (function() {
// some code
})();
Controller = (function(BudgetCrtl, UICtrl) {
var n = BudgetCrtl.getSum(3);
console.log(n);
})(budgetController, UIController);
In ES6 I attemted to use simply func expressions not IIFE's in order to pass the other modul in the controller modul and be able to use/pass over the public methods but it dod not work.
ES6 attempt:
let budgetController = function() {
const x = 20;
function add(a) {
return x + a;
}
return {
getSum: (b) => console.log(add(b))
}
}
UIController = function() {
// some code
}
Controller = function(BudgetCrtl, UICtrl) {
const n = BudgetCrtl.getSum();
console.log(n);
}
Controller(budgetController, UIController);
Could anyone provide me with some solution to involve somehow in ES6 the so called encapsulation and above mentioned things? Any idea would be appreciated!
Cheers, thank you!

You need to execute that BudgetCrtl to get access to the getSum function like so BudgetCrtl().getSum(3), since that BudgetCrtl is a function and not
a value returned from it's execution .
plus if you want the value to be stored to the n you should not console.log in the arrow function immediately, because the way it is now it's implicitly returning undefined
let budgetController = function() {
const x = 20;
function add(a) {
return x + a;
}
return {
getSum: (b) => {
let newVal = add(b)
console.log(newVal)
return newVal // so that you can store the value in `n`
}
}
}
UIController = function() {
// some code
}
Controller = function(BudgetCrtl, UICtrl) {
const n = BudgetCrtl().getSum(3);
console.log(n);
}
Controller(budgetController, UIController);

Related

Why does returning this ECMAScript Harmony arrow function expression produce unexpected behavior?

I've been playing with the new ECMAScript 6 features and this question has to do with arrow functions. The following code is a simple functional composition method assigned to the Function object's prototype. It works perfectly well using a simple anonymous function but does not when using an arrow function instead.
Function.prototype.compose = function (bar) {
var foo = this;
return function () {
return foo(bar.apply(null, arguments));
};
};
var addFive = function (baz) {
return baz + 5;
};
var addTen = function (hello) {
return hello + 10;
};
var addFifteen = addFive.compose(addTen);
console.log(addFifteen(10));
http://jsfiddle.net/oegonbmn/
Function.prototype.compose = function (bar) {
var foo = this;
return () => foo(bar.apply(null, arguments));
};
var addFive = function (baz) {
return baz + 5;
};
var addTen = function (hello) {
return hello + 10;
};
var addFifteen = addFive.compose(addTen);
console.log(addFifteen(10));
http://www.es6fiddle.com/hyo32b2p/
The first one logs 25 correctly to the console whereas the second one logs function (hello) { return hello + 10; }105 which doesn't exactly tell me what I'm doing wrong.
I am not returning the value within the arrow function since it is supposed to implicitly return the very last statement (the first and last in this instance) and I suppose the issue at hand has something to do with the lexical scoping and the values of this, maybe. Can anyone explain?
Both this and arguments are not (re)bound in arrow functions, but instead lexically scoped. That is, you get whatever they are bound to in the surrounding scope.
In ES6, using arguments is deprecated anyway. The preferred solution is to use rest parameters:
Function.prototype.compose = function (bar) {
return (...args) => this(bar.apply(null, args));
};
or, in fact:
Function.prototype.compose = function (bar) {
return (...args) => this(bar(...args));
};

Cross module function scope? Where is it looking

Given the following:
include.js
module.exports = function() {
...
return {
func: function(val) {
return Function('return ' + val + ';');
}
}
}()
running.js
var outer = function() {
var include = require('./include.js');
var x = include.func('eq');
console.log(x(5, 5));
}
outer()
...where would I put function eq(x, y){ return x === y; } such that this would work? I'm currently getting an eval at <anonymous> on the line that calls the function; x(5,5) in this case.
It doesn't like when eq is in include.js or when it's in running.js ~ I know this is example code is taken from my project and made pretty ambiguous...but, if it's possible, where would that function go?
OR
...would it be better to define an object of functions where the keys are the name of the function?
defaultFuncs = {
'eq': function(x, y){ return x === y; }
}
The parent scope of functions created via new Function is the global scope, not any local or module scope. So
global.eq = function(a,b) { return a==b };
function func(name) { return Function("return "+name+";"); }
var x = func("eq");
var equals = x();
equals(5, 5) // true
should work.
...would it be better to define an object of functions where the keys are the name of the function?
Definitely yes.

How can I reference a closure using a string the same way I do it with a member function without using eval?

We have some js code splitted in many files. We have a core file that defines code used by many other js files.
Currently we have something like this:
core.js:
window.mycore = function() {
var myfunction1 = function() {
};
var myfunction2 = function() {
};
var myfunction3 = function() {
//..
var a = myfunction1(b);
//..
};
//...
// many "myfunction"
//...
var myfunctionN = function() {
};
var publish = function() {
for(var i = 0; i < arguments.length; i++) {
try {
window.mycore[arguments[i]] = eval('(' + arguments[i] + ')');
}
catch(e) {
Log.err(600, arguments[i], e);
}
}
};
publish("myfunction1", "myfunction7", "myfunction8",/*...*/"myfunctionM")
}
app.js:
// ...
// ...
var result = window.core.myfunction1("myparam");
// ...
// ...
Note that none core methods are declared as members of the window.core object. Instead they are attached to the core object with the publish function.
This has some pros:
The core code can reference any core function without the need of writing "window.core."
We avoid writing "var myfunction = window.mycore.myfunction = function() ..." in every public function declaration
The exposed methods can be seen centraliced.
But, the use of eval in the publish function is bringing us problems when using code analysis tools since they don't tend to understand eval declarations.
So, here is my question.
Which is the better way to improve this code, so we can keep the advantages mentioned but eradicating the eval declaration.
I am aware of the solution of sending to the publish function some name/value pairs like publish({'myfunction1': myfunction1}, ... ), but I also want to avoid function name repetitions.
Consider that I am not looking for radical changes since there is a lot of code written already.
Thanks!
I'm not sure I understand completely your reasons for using the "publish" method, but is there any reason your not just returning an object with the correct functions from your constructor?
ie:
window.mycore = (function() {
var myFunc1 = function(a) {
alert(a);
};
var myFunc2 = function(b) {
// call to other function in the same scope
myFunc1(b);
}
...
// at the end just expose the public members you want
return {
myFunc1: myFunc1,
myFunc2: myFunc2
};
})();
or
window.mycore = (function() {
return {
myFunc1: function(a) {
alert(a);
},
myFunc2: function(b) {
this.myFunc1(b);
}
};
})();
or, yet another way to end up with the same object :) ... as always there are different ways to get there
(function(){
var o = {};
o.func1 = function(a) {
alert(a);
}
o.func2 = function(b) {
this.func1(b);
}
window.mycore = o;
})();
So, at a fundamental level, I think it would have benefitted you to have written those name spaces as objects. But thats a whole different subject entirely. (and it disqualifies based on the fact that you dont want to do a lot of refactoring).
With that said, my first idea was that you could probably sidestep the need for eval by using the .call() or .apply() method. What they allow you to do is to chain a function call out of your function name. but that doesn't apply to a "string" which is what you're giving your publish function.
so after googling, this is how you execute a function from a string:
var fn = window[settings.functionName];
if(typeof fn === 'function') {
fn(t.parentNode.id);
}
https://stackoverflow.com/a/912642/680578
Personally I prefer the #Jaime approach, but maybe you may do something like
window.mycore = function() {
function myfunction1() {
};
function myfunction2() {
};
function myfunction3() {
//..
var a = myfunction1(b);
//..
};
//...
// many "myfunction"
//...
function myfunctionN() {
};
var publish = function() {
for(var i = 0; i < arguments.length; i++) {
try {
window.mycore[arguments[i].name] = arguments[i];
}
catch(e) {
Log.err(600, arguments[i].name, e);
}
}
};
publish(myfunction1, myfunction7, myfunction8,/*...*/myfunctionM);
}

When a method depends on another method

What is the best way to deal with the following situation in JavaScript.
I have three methods (m1, m2, m3) and the last one (m3) depends from the results of the others two (m1, m2).
In this way it works, but I am curious to know if there is a better way to write the code in this situation, especially for future developers that will read the code.
var O = function () {
this.p = 0;
}
O.prototype.makesomething = function () {
var that = this;
that.m1();
that.m2();
that.m3();
}
O.prototype.m1 = function () {O.p++}; // it changes the value O.p
O.prototype.m2 = function () {O.p++}; // it changes the value O.p
O.prototype.m3 = function () {return O.p}; // m3 depends by m1, m2 because it needs to get the update value of O.p
First, I don't know for sure, but putting this.p = 0 inside O does not make sense in combination with O.p. You probably mean this.p inside m3, when referring to the instance.
Anyway, if you are looking for readability, you could make some simple but idiomatic functions like this: http://jsfiddle.net/ZvprZ/1/.
var O = function () {
this.p = 0;
}
O.prototype.makesomething = function () {
var that = this;
var result = when( that.m1(), that.m2() )
.then( that.m3() );
return result;
}
O.prototype.m1 = function () {this.p++};
O.prototype.m2 = function () {this.p++};
O.prototype.m3 = function () {return this.p};
The when/then can be rather straight-forward since it does not do anything than making it more readable:
(function(window) {
var when, then, o;
when = function() {
return o; // just return the object so that you can chain with .then,
// the functions have been executed already before executing
// .when
};
then = function(a) {
return a; // return the result of the first function, which has been
// executed already (the result is passed)
};
o = { when: when,
then: then };
window.when = when; // expose
window.then = then;
})(window);

Ways to create a singleton with private variables?

I'm trying to create a singleton that has variables not directly mutable from the outside. This is my current code:
var singleton = new (function () {
var asd = 1;
this.__defineGetter__("Asd", function() {
return asd;
});
})();
alert(singleton.Asd) // test
However, it seems like alot of ugly code just to achieve a simple thing.
What are some cleaner alternatives to create a singleton with such private variables?
var theStaticClass = (function () {
var a = 7;
return { get A() { return a; } };
})();
console.log(theStaticClass.A);
This is another (I wouldn't say less ugly) way, but now TheStaticClass.A is more like a getter method (the advantage being that it also works in IE):
var TheStaticClass = new (function() {
var a=1;
arguments.callee.prototype.A = function() {
return a;
};
})();
alert(TheStaticClass.A()) //=> 1
Suppose you need to do some modifications to the variable before returning:
var theStaticClass = (function () {
var a = 7;
return {A: (function(b){
return b * b;
})(a)};
})();
console.log(theStaticClass.A); // => 49
I think only closure can bring real private variable in JavaScript. Usually we use some kind of naming convention to tell if the variable is private.
var TheStaticClass;
(function () {
var a=1;
TheStaticClass.__defineGetter__("A", function() {
return a;
});
})();
alert(TheStaticClass.A) // test

Categories