Chain calls to the same function and modify an internal variable - javascript

Is this possible with javascript? Use the same function and call it again and again.
myFunc("test")("me")("please")()
EDIT
Thanks for the answers. I'd like to keep and internal variable that appends the string to the previous one if possible.

function MyFunc(arg){
console.log(arg);
return MyFunc;
}
MyFunc("a")("b")("c");
JsFiddle example
Y-combinator example:
function Y(f) {
var g = f(function() {
return g.apply(this, arguments);
});
return g;
}
var MyFunc = Y(function(f) {
var a = "";
return function(n) {
a = a + n;
console.log(a);
return f;
};
});
//alert(a); // throws error as a is outside of scope here
MyFunc("a")("b")("c"); # logs a; ab; abc

Yes, you can, if you will return arguments.callee;, example:
(function(param){console.log(param); return arguments.callee;})("test")("me")("please")
will log into console:
test
me
please

Related

Module pattern - separation of concerns - encapsulation in ES6

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);

Javascript - need explanation on the variable inside IIFE

I have this code - I just wonder why after I add 'var' to foo variable, it doesn't work (it shows me foo is undefined)... Can anyone help explain these two functions? Thanks!
window.onload = function() {
var test = foo().steps(2);
console.log(test);
}
(function() {
//if I remove var, then it prints out a function which is what I expected
var foo = function() {
var steps = 1;
function callMe(g) {
//do something else
console.log("hello" + g);
}
callMe.steps = function(x) {
//if no arguments then return the default value
if (!arguments.length) return steps;
console.log(arguments);
//otherwise assign the new value and attached the value to callMe
steps = x;
return callMe;
}
return callMe;
}
})();
adding var to foo makes foo a local variable inside the IIFE and thus you can't access it outside.

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.

Setting a variable in the closure scope

I think I understand why variables exist outside of the function they were declared in, because you're returning another function:
myFunction = function() {
var closure = 'closure scope'
return function() {
return closure;
}
}
A = myFunction(); // myFunction returns a function, not a value
B = A(); // A is a function, which when run, returns:
console.log(B); // 'closure scope'
The way that it's written now, calling A() is like a getter.
Q: How can I write myFunction so that calling A(123) is a setter?
Try the following:
myFunction = function() {
var closure = 'closure scope'
// value is optional
return function(value) {
// if it will be omitted
if(arguments.length == 0) {
// the method is a getter
return closure;
} else {
// otherwise a setter
closure = value;
// with fluid interface ;)
return this;
}
}
}
A = myFunction(); // myFunction returns a function, not a value
A(123); // set value
B = A(); // A is a function, which when run, returns:
console.log(B); // '123'
You could do something like this if you want both getter and setter for example:
var func = function() {
var closure = 'foo';
return {
get: function() { return closure; },
set: function(value) { closure = value; }
}
};
var A = func();
A.set('foobar');
console.log(A.get()); //=> "foobar"
Should be as simple as:
myFunction = function() {
var closure = 'closure scope'
return function(setTo) {
if (typeof setTo !== "undefined") {
closure = setTo;
return this; //support call chaining, good idea hek2mgl
} else {
return closure;
}
}
}
Since the closure variable is within the closure of the function's scope, you should be able to assign to it the same way you can read from it.
See jsFiddle: http://jsfiddle.net/WF4VT/1/
Another alternative would be to use a class and define getters and setters:
function MyClass(p){
this._prop = p;
}
MyClass.prototype = {
constructor: MyClass,
get prop(){
return this._prop;
},
set prop(p){
this._prop = p;
}
}
var myObject = new MyClass("TEST");
console.log(myObject.prop);
myObject.prop = "test";
console.log(myObject.prop);
Demo: http://jsfiddle.net/louisbros/bMkbE/
jsFiddle Demo
Have your returned function accept an argument. Use it as a setter:
myFunction = function() {
var closure = 'closure scope';
return function(val) {
closure = val;
return closure;
}
}
A = myFunction(); // myFunction returns a function, not a value
B = A(123); // A is a function, which when run, returns:
console.log(B); // 'closure scope'
Revisiting this question, I see that I could do it this way:
function outside() {
var result = 'initialized'
return inside
function inside(argVariable) {
if(arguments.length) {
result = argVariable
return this
} else {
return result
}
}
}
myFunction = outside() // outside returns a function
X = myFunction() // returns: 'initialized'
$('body').append(X + '<br>')
myFunction(123) // setter
X = myFunction() // returns: 123
$('body').append(X)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

In Javascript, is there a technique where I can execute code after a return?

Is there a technique where I can execute code after a return?
I want to return a value then reset the value without introducing a temporary variable.
My current code is:
var foo = (function(){
var b;
return {
bar: function(a) {
if(b){
var temp = b;
b = false;
return temp;
}else{
b = a;
return false;
};
}
};
})();
foo.bar(1);
I want to avoid the temp var. Is that possible?
var b holds a value between function calls because it is a memoization styled function.
Use a finally block to ensure certain code runs after another block. That block can include errors, returns, or whatever else. The finally block will run after.
try {
return 'something';
} finally {
// your after return code
}
In Javascript, is there a technique where I can execute code after a return?
Absolutely. It's called setTimeout(), but somehow I doubt that it would be a good solution for you.
Here it is anyway:
var foo = (function(){
var b;
return {
bar: function(a) {
if(b){
setTimeout(function() {b = false;},20);
return b;
}else{
b = a;
return false;
};
}
};
})();
foo.bar(1);
The function you passed as the first argument to setTimeout will "close around" the b variable, and set it after 20 milliseconds.
If you want to retain the synchronous flow of code execution, then absolutely not, unless you do it manually via a function that is returned along with the desired value.
Ultimately, your best bet will be the temp variable. You can close around it like the b variable if you wish:
var foo = (function(){
var b,temp;
return {
bar: function(a) {
if(b){
temp = b;
b = false;
return temp;
}else{
b = a;
return false;
};
}
};
})();
foo.bar(1);
it doesn't really matter what you set b to because you're declaring it with the var inside the function. It does not exist outside the function.
You really need to show your complete code here. In your example, b is always undefined, therefore the conditional would always enter the else case and secondly, since we got a lexical function scope in Javascript, b would always lose its value when the function ends.
So I guess you're taking advantage of closures to hold a reference to that variable. But its impossible to answer without seeing your actual code.
I don't understand anything about this code... but here you can do this :
function(a) {
var b;
// I suppose b is defined here ?
if(b)
{
b = false;
return !b;
} else {
b = a;
return false;
};
};
I think that this is not possible (or I don't know how to do it). I'll try to create a function that do whatever you want (i.e. reset variables) and then use return reset_variables();
The function 'reset_variables' also return the value what you want.
I don't think I would ever use something like this, but you could write a function for it:
var foobar = function(value, callback) {
callback();
return value;
};
Then it would be used like this in your code:
function(a) {
var b;
if (b) {
// The first argument is what you want returned.
// The second argument is a function that you want executed "after" you've calculated the return value
return foobar(b, function() {
b = false;
});
} else {
b = a;
return false;
};
};
I called it foobar because I simply can't think of a name for this concept :)
Obviously the code does not actually execute after the actual return (that would be impossible) but it does capture the value of your return value before the final function is executed, which results in something that looks like what you're after.
But, once again, I'm not really sure if I'd advice to use something like this :)
You can use:
Promise.resolve().then(() => console.log('your action'));
This is similar than using process.nextTick

Categories