Is there any way to share code between two closures?
Example:
// ANTIPATTERN
var cbDoThing = function cbDoThing(arg){
return typeof closed1 +" " + arg;
}
function getClosure1(closed1) {
return cbDoThing;
}
function getClosure2(closed1) {
return function(arg) {
// do other work
return cbDoThing(arg);
}
}
f1 = getClosure1();
f1("ARG1"); // returns "undefined ARG1"
f2 = getClosure2();
f2("ARG2"); // returns "undefined ARG2"
Here getClosure1() and getClosure2() return a closure that does similar tasks. I.e. both of them need to execute the cbDoThing() within a closure environment, but getClosure2() runs some other code in addition.
The above example does not work as wanted. cbDoThing() is defined in the global context, so closed1 variable is undefined. The wanted behavior is a pattern to make the closed1 variable be read from the closure scope chain, but without redefining the cbDoThing()function in each closure.
PS: JsFiddle playground.
EDIT:
Now that I asked, an answer came to me with minor modifications:
var cbDoThing = function cbDoThing(closed1, arg){
return closed1 +" " + arg;
}
function getClosure1(closed1) {
return function(arg) {
return cbDoThing(closed1, arg);
}
}
function getClosure2(closed1) {
return function(arg) {
// do other work
return cbDoThing(closed1, arg);
}
}
The cbDoThing does not access closed1 variable from the closure variable scope. Rather it is passed an extra argument. Then this function is called from each of the closures.
JsFiddle
Nice work. Javascript only walks down the prototypal chain, which means that cbDoThing has no reference or declaration of closed1. In this case, cbDoThing has only one prototype - Object. Without explicitly passing an argument to cbDoThing, it will not have any notion of the closed1.
Here is a thorough discussion of closures in javascript: http://jibbering.com/faq/notes/closures/
Related
I'm confused between these two closure functions.
The doSomeMath returns the function without executing it when I assigned it to a variable, test. It will only run the closure function when I do test();
However this is not the case for showName function. As soon as I pass in the values, it calls the closure function right away instead of returning it.
Can someone kindly explain it to me? Thanks.
function showName (firstName, lastName) {
var nameIntro = "Your name is ";
// this inner function has access to the outer function's variables, including the parameter
function makeFullName () {
var full = nameIntro + firstName + " " + lastName;
return full;
}
return makeFullName ();
}
showName ("Michael", "Jackson"); // Your name is Michael Jackson
function doSomeMath(a, b) {
var a = a;
var b = b;
function multiply() {
var result = a * b;
return result;
}
return multiply;
}
var test = doSomeMath(5,10);
test();
These two functions are two different ways of demonstrating how closures work.
You could as easily have done the opposite to achieve the same effect.
function doSomeMath(a, b) {
var a = a;
var b = b;
function multiply() {
var result = a * b;
return result;
}
return multiply();
}
doSomeMath(5,10) //50
In the above code you return the result of invocation of the inner function instead of the function itself. Here, as you can see, multiply has a closure over 5 and 10 and so you get the outcome as 50.
Similarly, try:
function showName (firstName, lastName) {
var nameIntro = "Your name is ";
// this inner function has access to the outer function's variables, including the parameter
function makeFullName () {
var full = nameIntro + firstName + " " + lastName;
return full;
}
return makeFullName;
}
var show = showName ("Michael", "Jackson");
show() //"Your name is Michael Jackson"
The above code returns the inner function instead of its invocation and in turn demonstrates how the inner function, makeFullName has a closure over the nameIntro variable of the outer function.
The other answer provides a concise understanding on closures. To know more read up on closures to understand the above examples better.
I think you are confusing closures and higher order functions.
There is no such concept as manually calling a function. A function must always be called. This does not change if the function is a closure.
In fact one might say that this is the essential power of closures as an abstraction mechanism.
A closure is a function that references elements in its enclosing scope.
This is often referred to as lexical scoping.
The set of elements of the enclosing scope that are referenced by a closure are known as its environment.
A function that does not refer to elements in its enclosing scope can be thought of as a degenerate closure - a closure with an empty environment.
The value returned by a function may be another function but this is purely orthogonal to the notion of closures.
In JavaScript, as in many languages, functions are first class values. This means that they can be stored in variables, passed as arguments, and returned as results.
Consider
var createIncrement = function (incrementBy) {
return function (value) {
return value + incrementBy;
};
};
The function above is higher order, because it returns a function. Incidentally, it is also a closure because it references incrementBy which is declared in an enclosing scope.
The confusion expressed in the framing of your question likely arises from the fact that, in practice, the two features will be used together in even the simplest of JavaScript programs.
I found a half decent explanation on closures a while ago on this website. They present us with the following factory function to see a working closure:
var car;
function carFactory(kind) {
var wheelCount, start;
wheelCount = 4;
start = function() {
console.log('started with ' + wheelCount + ' wheels.');
};
// Closure created here.
return (function() {
return {
make: kind,
wheels: wheelCount,
startEngine: start
};
}());
}
car = carFactory('Tesla');
// => Tesla
console.log(car.make);
// => started with 4 wheels.
car.startEngine();
Why does this person return the closure as a immediately-invoked function expression (IIFE) that returns an object with the properties that he wants to share? I feel like the IIFE is unnecessary. If I would just return the object straight away, this would result in the same thing. Am I missing something?
//Closure created here
return{
make: kind,
wheels: wheelCount,
startEngine: start
};
Yes I don't think you are missing anything.
Just made to show the creation of a closure. If you just return the object it would not be considered one (not the best example though).
According to a comment of the author in that website:
You need the self-executing function because that is the act that
creates the closure. JavaScript only has function-level scope so the
only way to bind the free variables into the enclosing scope is by
invoking a function.
This could make sense if carFactory() whould be some object's method. Then the this of returned object (as self-invoked function) would be changed.
var obj = {};
obj.funA = function(){
return {
getThis:this
};
};
obj.funB = function(){
return (function(){
return {
getThis:this
};
})();
}
console.log(obj.funA()); //object
console.log(obj.funB()); //window
So I have this code:
function fn(a){
var f=(new Function("return a"));
return f();
}
fn(7)//ReferenceError: a is not defined
Same problems with local variables:
function fn(){
var a=7;
var f=new Function("return a");
return f();
}
fn(7)//ReferenceError: a is not defined
I want it to return a but the new function cant see a,
it can only see global a
var a=1;
function fn(a){
var f=(new Function("return a"));
return f();
}
fn(7)//1
With the normal initialization the function can see the argument.
function fn(a){
var f=function(){return a};
return f();
}
fn(7)//7
I need to call the basic constructor in my project and can't use global variables.
I know that i could solve this by giving arguments to the newly created function and call it with that like this:
function fn(a){
var f=(new Function('a',"return a"));
return f(a);
}
fn(7)//7
And also could use some parsing function and some stupidly long method to make incoming arguments reachable like this:
function parsargs(funct){
//some parsing methodes giving back argument name list from funct.toString()
return "['a','b']";//like this
}
function fn(a,b){
var arrgstr,retfunc;
arrgstr="";
for(var i in arguments)
{
if(i<arguments.length-1)
arrgstr+=arguments[i]+",";
else
arrgstr+=arguments[i];
}
//return arrgstr;
retfunc="var f=new Function("+parsargs()+",'return b*a');return f("+arrgstr+")";
return (new Function(retfunc))();
}
fn(7,4)//28
But there must be an easier way which reaches local variables and functions as well...
Any suggestions?
PS:
i am trying to replace eval() in the project
Here is a simplified version of my original problem:
fiddle
The answer is NO...
Your exact question isn't clear but, supposing you can use arguments.callee (i.e. non strict mode) and that you want to be able to have any arguments name in fn, you "may" do this:
function fn(a,b){
var strargs = arguments.callee.toString().match(/\(([^\)]*)\)/)[1];
return (new Function(strargs.split(","),"return a+b")).apply(null,arguments);
}
console.log(fn(7, 3)) // 10
But I have a strong feeling this is a XY question and that we could have given a more useful answer knowing the real original problem to solve.
You could call your new Function with a context that references the local variables that you need:
function f(a) {
var b = 30;
return new Function("return this.a + this.b").call({ a: a, b: b })
}
f(10) // 40
The reason why this isn't working as easy as you would like is that JavaScript doesn't blindly put variables in a scope. Instead, it parses the function body (as good as it can) and determines which variables the code will need. It will then look up the variables in the outer scopes, create references for them and attach those references to the new function. That's what keeps variables from the outer scope accessible inside of the function when it eventually will be executed.
You want to build a function from a string body. JavaScript can't tell which variables the body will use and hence, it won't make those variables available.
To make it work for function arguments, use apply()::
function fn(a){
var argref = arguments; // create reference to the arguments of fn() and hence to a or any other arguments
var func = new Function("return arguments[0]");
var wrapper = function() {
return func.apply(null, argref);
};
return wrapper;
}
Note that you still can't reference arguments by name since the code never specifies what the names of the arguments of func are - JavaScript can't magically read you mind and do what you want. If you want to access the arguments by name, you need to tell the interpreter the names.
This question has some code how to determine the names from a function reference: How to get function parameter names/values dynamically from javascript
I don't see a way to make local variables available without passing them to fn() as arguments. Even if you used them inside of fn(), they would be out of scope when func() is eventually executed.
A simple solution would be to pass an object to fn():
function fn(conf) {
var func = new Function('conf', "return conf.a");
var wrapper = function(conf) {
return func.apply(null, conf);
};
return wrapper;
}
fn({a:7});
new Function doesn't create a closure context, but eval does.
Here's a low-tech way to build a function with an arbitrary evaluated body and access to the calling scope:
function f(a) {
return eval("(function() { return a })")()
}
f(10) // 10
En example can be found in Twitter'a typeahead.js here:
function () {
// ...
return this.each(initialize);
function initialize() {
// ...
}
}
Questions:
What are the scopes and what function sees what?
What is the reason for using such a construct (usage scenarios and advantages)?
Javascript has function based scope, which means that every thing defined inside a function is available from the first line, since the definition is "hoisted" by the complier.
That goes for both variable and function definitions - variable values however, are not available until after assignment.
You can read all about javascript scoping and hoisting here
This means that the function initialize is available from the first line of the wrapping anonymous function.
There is no real reason, and no advantages, for doing it that way, unless you count the code structure as an advantage.
Personally I don't see any reason to do this. For me even it looks a little bit weird. Martin is right. You should be careful, because the defined variables are not accessible like functions. For example this doesn't work:
var getValue = function(func) {
return func();
}
var f = function() {
return getValue(now);
var now = function() {
return 10;
}
}
alert(f());
However, this works:
var getValue = function(func) {
return func();
}
var f = function() {
return getValue(now);
function now() {
return 10;
}
}
alert(f());
Let's consider simple singleton implementation:
var singleton = function (Constructor) {
var singleton;
return function () {
if (!singleton) {
singleton = new Constructor();
}
return singleton;
};
};
We could move declaration of singleton variable to arguments:
var singleton = function (Constructor, singleton) {
return function () {
if (!singleton) {
singleton = new Constructor();
}
return singleton;
};
};
So I simply curious about side effects.
One more example:
var counter = (function (i) {
return function () {
i = (i || 0) + 1;
return i;
};
}());
We could move declaration of singleton variable to arguments
First, let's make it possible to talk about this without tying outselves up in knots by using the same symbol (singleton) for two completely different things within the same few lines of code.
Here's your seecond example renamed:
var singleton = function (Constructor, instance) {
return function () {
if (!instance) {
instance = new Constructor();
}
return instance;
};
};
If you did that, then calling the singleton function with two arguments would specify instance, making passing Constructor in pointless — Constructor would never be called by singleton (again, if you passed in two args [and the second arg was truthy]). So it would be a bit odd to do that.
But you asked about side-effects. There are no external effects involved if you assign to a formal argument within the function. It doesn't, for instance, have any effect outside the function:
function foo(arg) {
arg = 67;
}
var a = 42;
foo(a);
console.log(a); // Still 42
However, assigning to an argument rather than to a local variable does, in non-strict mode, have a small cost, because there's overhead involved: It relates to the magic arguments pseudo-array. In non-strict mode, there's a link between the formal arguments of a function and the arguments pseudo-array:
function foo(a, b) {
console.log(a);
console.log(b);
b = 42;
console.log(arguments[1]);
}
If we call that like this:
foo(1, 2);
we see
1
2
42
Note the magic: Assigning to the formal argument b updated the pseudo-array arguments. (It works the other way, too.) That link has a small but real runtime cost.
(In strict mode, there is no link, for this very reason.)
As far as closure goes, there is no difference in the two implementations. However, in first example, singleton is not settable by the caller.
I will choose between the two implementation, just based on whether singleton could have been created outside these example functions or not. If it can be, use model 2 otherwise use model 1