Return in Revealing Module Pattern - javascript

I read Addy's book here about revealing module patter. However, if you execute the example code it actually returns undefined. A fix is to add 'return' before each called functions. Am I supposed to add return for each functions being called if using RMP? Is this the right way to make it work? What am I missing?
var myRevealingModule = (function () {
var privateCounter = 0;
function privateFunction() {
privateCounter++; <--need to add return
}
function publicFunction() {
publicIncrement(); <-- need to add return
}
function publicIncrement() {
privateFunction(); <--need to add return
}
function publicGetCount(){
return privateCounter;
}
// Reveal public pointers to
// private functions and properties
return {
start: publicFunction,
increment: publicIncrement,
count: publicGetCount
};
})();
myRevealingModule.start(); <-return undefined
http://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript

The issue nas nothing to do with RMP but rather with functions and return values.
Why would you expect a method that doesn't return anything to actually return something other than undefined?
Take a closer look here. The start in fact calls publicFunction but the body of the latter doesn't return anything.
Yet you call it and expect a value.
The answer to your question is then: yes, if you want a value back from the function, you have to return it.
In this particlar example they have a method count to return current value. Two other methods are just used to control the counter.

Related

javascript two brackets after function name

What does below syntax means?
connect(mapStateToProps, mapDispatchToProps)(Home)
I understand we are passing two arguments to a function, but what is the purpose of below one?
(Home)
It doesn't look like node but Redux and as in a comment not an ES6 thing.
What it is: Connect is a higher order (factory) function ie. it returns a function. And it is that returned function which is immediately called with Home
Take a look and an example of mock of connect below
function connect(param1, param2) {
return innerFunction (innerParam) {
console.log(`${param1} ${innerParam} ${param2}`)
}
}
connect('A','B')('precedes')
// outputs 'A precedes B'
Edit: Added an example.
A function can return a function, and you can call this returned function immediately.
For information and as already stated in comments, the fact of decomposing one function call into smaller like this one in your example is called currying and is a common practice in JavaScript (more info here : What is 'Currying'?)
This example might help you :
function function1(info) {
return function(innerParam) {
console.log(`Hello this function has info ${info} and has just been called with this param: ${innerParam}` )
}
}
function1('Bobby')('Alice');
// same as :
var bobbyFunction = function1('Bobby');
bobbyFunction('Alice');
This is useful to dynamically generate a function that depends on some parameter, but can still be called several time with some other changing parameters. Imagine this, for instance :
var bobbyFunction = function1('Bobby');
['Alice', 'Tommy', 'Johny'].forEach(name => bobbyFunction(name));
It's plain javascript. Function connect returns another function and code immediately calls it with parameter Home.
function first(f) {
return function second(s) {
console.log(f, s);
}
}
// this
first('one')('two');
// is same as this
var x = first('one');
x('two');
see this example:
connect(mapStateToProps, mapDispatchToProps)(Home)// just like code below
function f(){
//do something
}
function connect(a,b){
return f;
}
connect(mapStateToProps, mapDispatchToProps);//first,return f;
connect(mapStateToProps, mapDispatchToProps)(Home)//second,return f(home);

How to know if the called method is the last one

Having an object like this:
var foo = {
a: function () {
/*
if (lastCall) {
return this.b();
}
*/
...
return this;
}
, b: function () { return ...; }
};
How can I know, inside of the a method if the current a call is the last?
foo.a().a().a().a()
// ^- This should return another value
// while the other calls return `this`
I know I can use a boolean value or something in the last call, but if possible, I would like to avoid that.
So, is it possible to check if the current call is the last one in the stack?
When you are in a, the next a is not called yet. So you can't know there will be an other call to a after this one.
You can get the stack with an Error object like this :
var stack = new Error().stack;
But the stack won't help you. The next call to a is not in the stack.
I'm pretty sure you can't do this without a syntax change like foo.a().a().b(); or foo.a().a().a(true);.

Why is 'break' in JS forEach function not allowed?

I've done quite a bit of reading and seen many different questions regarding this topic, but I was wondering if I could get help on WHY breaking out of a For Each loop doesn't work. Also, I am pretty new, so I apologize in advance if this question was answered in a different way that I wasn't able to understand.
So far, I have written a forEach function to emulate a native .forEach method:
function forEach(collection, callback){
if(collection.isArray){
for(var i =0;i<collection.length&&callback(collection[i])!==false;i++){
callback(collection[i]);
}
}else{
for(var key in collection){
callback(collection[key]);
}
}
}
When I try to utilize this to write another function 'find' that searches for the first instance of the array that matches a criteria, using 'return' or 'break' doesn't seem to work. find([1,2,3,4,5].function(x){return x>3;}); returns 5 instead of 4.
function find (collection, criteria){
var result;
forEach(collection, function(x){
if(criteria(x)){
result =x;
return false;
}
});
return result;
}
I have been able to recreate the effect that I want using other functions, but would like to understand why this doesn't work, as I am learning how to implement the use of functions within other functions.
Thank you.
Consider the behavior of bar in this code snippet:
function foo(x) {
return x;
}
function bar() {
foo(1);
foo(2);
return 3;
}
console.log(bar());
It calls foo, which returns, but it is returning control back to bar itself, not to the caller of bar, so this logs 3.
The situation does not change if we put the definition of foo inside bar:
function bar() {
function foo(x) {
return x;
}
foo(1);
foo(2);
return 3;
}
console.log(bar());
Nor does it change if we accept it as a parameter:
function foo(x) {
return x;
}
function bar(baz) {
baz(1);
baz(2);
return 3;
}
console.log(bar(foo));
The behavior does not change when we use a function expression, either:
function bar(baz) {
baz(1);
baz(2);
return 3;
}
console.log(bar(function(x) {
return x;
}));
So the reason return does not work the way you are expecting from a function passed to forEach is that return retains its usual meaning of returning from the function it is in—not the function that lexically encloses that function. Similarly, break is illegal because it is not in a loop; it is in a function (that only happens to be called in a loop later on).
For an array, collection.isArray is undefined. You should replace this with Array.isArray(collection).
For non-array types, you're not checking the return value of callback(collection[key]).

return function call and tertiary conditional not working

I am having a devil of a time trying to figure this out. I have a function that returns the value of another function. Within the second function I have a tertiary conditional and it will NOT get that return.. I can't figure it out. I am sure it is a scope issue, but i can't solve it. This is all within a jquery plugin.
somefunctionA: function(){
var self = this;
var data = somecollection_of_data;
var storeReturn = $.map( data, function( obj, i) {
return (function(i){
return self._returnFilteredData(id);
})(obj.i);
});
},
__returnFilteredData: function(i){
var self = this;
if(some_conditionals){
return (
self.url ?
(function(){
if(some_more_conditionals){
self._getDBdata(); <<-- NEVER FIRES OFF
}
}) : self._getDBdata() <<--- THIS ONE FIRES OFF
)
}
}
},
so what ends up happening is I get a "null" in the storeReturn array because in some conditionals that first tertiary fails. I cannot get into it... to test.
the "_getDBdata()" function just returns a hash based on some other data.
Any ideas on what is happening? I tried everything and I can't solve this scope/closure issue.
First: this is horribly convoluted and you should stop doing it this way. Break it out into separate pieces.
Second: you're never calling the anonymous function in that situation, you're simply returning it. Adding another set of () will fix that, so that you call it and return its value:
__returnFilteredData: function(i){
var self = this;
if(some_conditionals){
return (
self.url ?
(function(){
if(some_more_conditionals){
return self._getDBdata();
}
})() : self._getDBdata()
)
}
}
},
In the ternary statement inside __returnFilteredData() you are, depending on the truthiness of self.url, returning one of two possible things. Whatever is returned is then returned from the callback that you provide to $.map().
If self.url is truthy, you return a function:
(function(){
if(some_more_conditionals){
self._getDBdata(); <<-- NEVER FIRES OFF
}
})
...but if self.url is falsy, you return the result of calling a function:
self._getDBdata()
In the case of the anonymous function, nothing ever actually calls it, but even if something did call the anonymous function it is not actually returning a result, it conditionally calls self._getDBdata() without returning the result.
You could change this to an immediately invoked anonymous function that returns a result:
__returnFilteredData: function(i){
var self = this;
if(some_conditionals){
return (
self.url ?
(function(){
if(some_more_conditionals){
return self._getDBdata(); // added "return"
}
})() : self._getDBdata() // added "()" after "})"
)
}
}
},
...but even then the anonymous function can still return undefined since it has no else case. Also __returnFilteredData() can return undefined if it never enters the main if block. Maybe undefined is an acceptable result for some cases, but this is far from obvious with the current code structure.
It would be much clearer and easier to maintain if you removed the anonymous function and the ternary and coded __returnFilteredData() to use an if / else if / else if structure.
Just a comment:
You are saying you can't get if..else to work, but I think you can't see the forest for the trees. If you get rid of the anonymous function you also get rid of self and the whole thing becomes very much simpler.
Note that whether this.url evaluates to true or false, you still call this._getDBdata(), so you just need to conditionally do the "some more conditionals" part:
__returnFilteredData: function(i) {
if (some_conditionals) {
if (this.url) {
if (some_more_conditionals) {
// do stuff
}
}
return this._getDBdata();
}
},

Eloquent Javascript chapter 10 modules

I am at the end of the modules chapter, but I don't really understand the whenDepsLoaded() part of this code. Could someone explain it for me please?
for example, what does this line do?
if (!deps.every(function(m) { return m.loaded; }))
return;
And this line?
myMod.onLoad.forEach(function(f) { f(); });
var defineCache = Object.create(null);
var currentMod = null;
function getModule(name) {
if (name in defineCache)
return defineCache[name];
var module = {exports: null,
loaded: false,
onLoad: []};
defineCache[name] = module;
backgroundReadFile(name, function(code) {
currentMod = module;
new Function("", code)();
});
return module;
}
function define(depNames, moduleFunction) {
var myMod = currentMod;
var deps = depNames.map(getModule);
deps.forEach(function(mod) {
if (!mod.loaded)
mod.onLoad.push(whenDepsLoaded);
});
function whenDepsLoaded() {
if (!deps.every(function(m) { return m.loaded; }))
return;
var args = deps.map(function(m) { return m.exports; });
var exports = moduleFunction.apply(null, args);
if (myMod) {
myMod.exports = exports;
myMod.loaded = true;
myMod.onLoad.forEach(function(f) { f(); });
}
}
whenDepsLoaded();
}
for example, what does this line do?
if (!deps.every(function(m) { return m.loaded; })) return;
It checks if there is at least one dependency that has not been loaded.
Array.prototype.every() basically iterates over the whole array and invokes the "test" function that you pass to it. In this example, it check if an object has loaded property set to a truthy value. But because there is a negation in from of that every call, it means that if not every dependency has been loaded, it will return from the function.
And this line?
myMod.onLoad.forEach(function(f) { f(); });
Since mod.onLoad contains an Array of functions, it simply invokes these functions one by one.
You should look at Array.prototype.forEach() documentation.
Work step by step from the inside out
Start at the inside of the puzzling statement and work outwards. That way there is less to think about at each stage.
if (!deps.every(function(m) { return m.loaded; })) return;
The innermost part is function(m) { return m.loaded; }. This is a function that takes an object and returns its "loaded" property, i.e. whether it is loaded.
The .every function takes an array and only answers true if all the elements in the array pass the test inside the parentheses.
Therefore deps.every( ..... ) takes the deps array and tests all its elements, for the presence of the ".loaded" property being true. If all of them are true, which means in practical terms that all the dep[endencie]s are loaded, then deps.every... is true.
By making the if statement test for !deps.every, that statement is looking to see if ANY of the deps are NOT loaded, and if so the entire function returns at that stage.
myMod.onload
myMod.onLoad.forEach(function(f) { f(); });
Here, function (f) { f(); }; is defining an anonymous function whose input is another function, and which executes that (other) function. For example, if you pass the anonymous function an input of console.log("hello"), it will print "hello" to the console.
myMod.onLoad is a list of functions that are designed to be run when the module loads. myMod.onLoad.forEach() is a way of iterating automatically over all of those functions, and feeding them into the anonymous function described above, which arranges for those functions to be executed.
The overall effect is that the statement scans through all the functions listed in myMod.onLoad, and executes them.

Categories

Resources