Working through Javascript Koans, I'm getting hung up on the following code:
it("should use lexical scoping to synthesise functions", function () {
function makeMysteryFunction(makerValue)
{
var newFunction = function doMysteriousThing(param)
{
return makerValue + param;
};
return newFunction;
}
var mysteryFunction3 = makeMysteryFunction(3);
var mysteryFunction5 = makeMysteryFunction(5);
expect(mysteryFunction3(10) + mysteryFunction5(5)).toBe(FILL_ME_IN);
});
It gets 23, and that's fine. The thing I'm puzzled by is how/why the parameter given to the 'mysteryFunction3' variable gets passed to the doMysteriousThing function as 'param'.
Is it just a fact of life that if there's an inner and an outer function which each take one parameter, defining a variable equal to the outer function given a specified parameter like:
var mysteryFunction3 = makeMysterFunction(3);
will make it so that sending a parameter to the variable instance of the outer function, like:
mysteryFunction3(10)
will cause that parameter (10) to be read as the parameter for the inner function?
I struggled through understanding this as well at first. This is how I reached clarity with it blow for blow. This is my first post on stack and excuse my being long-winded about it.
Let's take a very basic function that returns a string:
function fun() {
return 'Hi!';
}
If we log the above function without the invocation parentheses, the console just logs a reference to the function:
console.log(fun); //logs ---> [Function: fun]
If we log it again, but WITH the invocation parenthesis:
console.log(fun()); //logs ---> Hi!
the invocation of a function is equal to its return value:
console.log(fun() === 'Hi!'); //logs ---> true
So building off of that, let's rewrite our function to have another function declared within it that returns a string. The outer function will return the invocation of the inner function:
function funAgain() {
function innerFun() {
return 'Hello there!';
}
return innerFun();
}
So within the scope of funAgain (innerFun() === 'Hello there!') evaluates to true so when we log an invocation of funAgain to the console:
console.log(funAgain()); //logs ---> 'Hello there!'
But what if we left off the invoking parentheses of innerFun in the return statement of the outer function?
function funAgain() {
function innerFun() {
return 'Hello there!';
}
return innerFun;
}
console.log(funAgain()); //logs [Function: innerFun]
The function ITSELF is returned. Though it's not actually the whole story, we could think of (funAgain() === innerFun) Obviously, you can't actually run this comparison in practice because of scoping issues (innerFun can't exist outside of an invocation of funAgain).
BUT! Let's for a moment think of it that way. That means that if we capture the return value of funAgain in a variable:
var innerFunCaptured = funAgain();
console.log(innerFunCaptured); // logs [Function: innerFun]
We have, again conceptually, (innerFunCaptured === innerFun) ...
So now that our variable is bound to the inner function, we can invoke that inner function by adding parentheses to the variable.
console.log(innerFunCaptured()); //logs ---> 'Hello there!'
When I was talking about the "whole story" above, what I left out was that the inner function's binding to the variable is the result of the outer function's invocation, so really the binding not only includes innerFun itself, but ALSO the environment which it was created within including any potential arguments passed through the invocation of the outer function, which allows us to...
Rewrite the outer and inner function once more so that they now have parameters which interact:
function funOnceMore(greetingPartOne) {
function innerFun(greetingPartTwo) {
return greetingPartOne + ' ' + greetingPartTwo;
}
return innerFun;
}
What if we log funOnceMore with an argument.
console.log(funOnceMore('Hello')) //logs ---> [Function: innerFun]
Again, innerFun itself is returned. But what about the argument greetingPartOne we passed? Well, it was passed alright, but since innerFun was never invoked within funOnceMore, greetingPartOne was never used in any meaningful way. We have to figure out how to invoke innerFun! The answer: we need to bind it to a variable like we did in the previous step.
var innerFunCapturedAgain = funOnceMore('Hello')
Now innerFunCapturedAgain holds innerFun AND the environment of funOnceMore with the argument 'Hello' that we passed into it.
So now we can invoke innerFun by putting parentheses on innerFunCapturedAgain, and those parentheses will encapsulate the argument for greetingPartTwo that we pass to innerFun.
console.log(innerFunCapturedAgain('there!')) //logs ---> 'Hello there!'
Both the answers are very helpful, but struggling through this myself, I think the best answer is to just walk through what's happening and change it just enough to shed a new light on it:
makeMysteryFunction makes a function which adds its argument (makerValue) to the argument that's being passed to the function that it returns (mysteryFunctionX).
So, what helped me understand this is converting the numbers to strings:
function makeGreeting(greeting)
{
var newFunction = function greet(name)
{
return greeting + ' ' + name;
};
return newFunction;
}
var makeGreetingHi = makeGreeting('Hi');
var makeGreetingHello = makeGreeting('Hello');
//finally call functions
makeGreetingHi('Stranger');
//Hi Stranger
makeGreetingHello('Friend');
//Hello Friend
All I did was change the name of the functions, and concatenate strings instead of adding numbers. What makes the koan confusing is the function names: guess thats a good example of bad practices. The point of the exercise is simply that in the example I provided the greet function has access to greeting. Unfortunately thats lost in the nomenclature
Something that I just found extemely usefull in understanding what exactly is going on here is adding a console.log to show the contents of "mysteryFunction3". So:
var mysteryFunction3 = makeMysteryFunction(3);
var mysteryFunction5 = makeMysteryFunction(5);
console.log(mysteryFunction3);
expect(mysteryFunction3(10) + mysteryFunction5(5)).toBe(FILL_ME_IN);
The console output was this:
doMysteriousThing(param)
{
return makerValue + param;
}
Coming from a C# background, this is crazy. But at least I understand it now!
Related
I though that once createFunction runs I'll have access to the inner function.
function createFunction() {
function printHello() {
return console.log("hello");
}
return printHello;
}
// Both of these return undefined
createFunction(printHello());
createFunction.printHello();
Any thoughts?
Proper syntax is:
createFunction()();
... or, a bit more wordy:
const returnedFunction = createFunction();
returnedFunction();
... as printHello name makes any sense only within createFunction, but its value is actually returned by that function. And yes, it's perfectly ok to place any number of () in sequence you want.
As a sidenote, returning the result of console.log('hello') makes little sense: logging itself is a side effect, no need to check its result.
I though that once createFunction runs I'll have access to the inner function.
No, you cannot access a variable that is inside of a function outside of it. If you call a function those variables exist, but you cannot access them. However if a value gets returned, you can work with the function call as if it would be that expression. In your case you return the function so you can access it as:
var print = createFunction();
print();
Or as a oneliner:
createFunction()();
In your code createFunction returns another function, so to execute inner function you must call inner function by appending () after return value of createFunction i.e createFunction()();
createFunction() give printHello = function definition
createFunction() () same as printHello**()**
Also if we simplify your code we can re-write as
function printHello() {
console.log("hello");
};
function createFunction() {
return printHello;
};
console.log("return value of: createFunction()");
console.log(createFunction());
console.log("return value of: createFunction() () --> printHello()");
createFunction()();
I'm trying to get a solid understanding of closures, and I'm struggling with the mechanics of it. I've looked on w3schools (https://www.w3schools.com/js/js_function_closures.asp) and MDN (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures) and a few other places. I understand what a closure is and how to make it work but I don't understand why subsequent calls after the first call to the outer function just seem to go straight to the inner one instead.
Here is my code - a simple, working closure:
var add = (function () {
var a = 0;
alert('hi');
function addInner(){
a += 1;
return a;
}
return addInner;
})();
function getAdd() {
document.getElementById("test").innerHTML = add();
}
I have two questions that probably both have the same answer: Why does a not get reset every time I call add()? And why does the alert not pop up except for on the first time?
I attached getAdd() to a button, and it works great, but it but doesn't pop up with the alert past the first time. Why does it do this?
Edit: I also found the first answer to this question (Why Don't Variables Reset in a Closure (Javascript)) really helpful.
add is a reference to addInner, not the anonymous "outer" function, since the "outer" function returns addInner. Then, you call that anonymous function once - that last set of ()- and store the resulting function, with its own private 'a', in add.
Imagine that the outer function was a named function called constructAdder, and you called
var add = constructAdder();
var add2 = constructAdder();
That's basically what you've done, but with an anonymous function, if that makes it any clearer. You have an outer function that constructs an inner function that can count, due to the magic of closures.
Those questions do both have the same answer. And it's fairly simple. This statement:
var val = (function() {
return 42
}())
sets val to 42. Not a function. This is called an IIFE, or immediately-invoked function expression. We are declaring a function and calling it immediately. We never save that function. We just use it once to get the value it returns:
val // 42
Contrast that to:
var val = function() {
return 42
}
In this case we set val to a function that, when called, returns 42.
val() // 42
val() // 42
We can get pretty crazy with IIFEs:
var val = (function() {
return (function() {
return (function() {
return 42
}())
}())
}())
The value returned by that mess is still 42.
val // 42
All those functions are declared once, used once, and thrown away. But IIFEs are capable of so much more:
var add = (function() {
var counter = 0
return function() {
return counter++
}
}())
We're now using the IIFE to create a private variable! counter cannot be accessed outside the scope of the IIFE. It's safe. But the inner function can access and modify it. It's a fully encapsulated, stateful function!
add() // 0
add() // 1
counter // Uncaught ReferenceError: counter is not defined
This is what your code is doing:
var add = (function () {
var a = 0;
alert('hi');
function addInner(){
a += 1;
return a;
}
return addInner;
})();
It is encapsulating the a variable so that it cannot be accessed outside the scope of the IIFE. The addInner function, however, does have access to a and can modify it at will.
The alert() is only called once because that IIFE is only called once, then thrown away. Note that the function itself is the only thing thrown away. Since addInner maintains a reference to the scope (closure) created by the IIFE, that scope is safe from garbage collection.
In fact, that's a helpful way to think about IIFEs:
var val = function() {}
creates a function and
val()
creates a closure (the context that the function's body runs in). IIFEs are used when we don't care about the function, we just want the closure it creates.
Hope this helps. Have fun out there!
var add = (function () {
var a = 0;
alert('hi');
function addInner(){
a += 1;
return a;
}
return addInner;
})(); <-- This
The () at the end means that add is added forever, and if you look at the line above, then it says return addInner. This means that add() is actually addInner(), the good thing with this is that addInner has access to a. Actually writing the function like this is more proper.
var add = (function () {
this.a = 0;
alert('hi');
var addInner = function(){
this.a += 1;
return this.a;
}.bind(this);
return addInner;
})();
Because now you would think that add.a would make a available because it is written as this.a, but since addInner is returned, then it is not available.
You should focus on the
(function(){
// impl
})()
block.
It is called an Immediately Invoked Function Expression or IIFE.MDN reference
So when the code executes to line 1, it first evaluate the right side and the IIFE returns a closure which was then assigned to the variable add. Meanwhile, an alert was invoked in the IIFE. Understanding the IIFE can help you solve the problems.
In my opinion , the key is IIFE, after the code below is executed at the first time,
var add = (function () {
var a = 0;
alert('hi');
function addInner(){
a += 1;
return a;
}
return addInner;
})();
(Look out ! There is no add() in the code above because IIFE will be Invoked Immediately and the return addInner finished the initialization of variable add )
the function add has been changed to :
add = function addInner() {
a += 1;
return a;
}
Of course, the alert() only executed one time because the add has been changed at the begining.
Why does a not get reset every time I call add()?
And why does the alert not pop up except for on the first time?
that is the answer of your question.
variable a didn't destroy because the function add still have a reference, and this is about the closure.
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
I have tried folllowing two ways of referring a function:
First
let a = function() {
somefunction();
}
Second
let a = somefunction;
Where somefunction is the following in both cases:
function somefunction() {
alert("hello");
}
Is there any difference between these two ways?
Yes, there is a difference between your two examples.
In the first case, you are defining a new anonymous (unnamed) function which calls somefunction. You are then assigning your new function definition to the variable a. a holds a reference to your new function.
In the second case, you are simply assigning your original function of somefunction to the variable a. The variable a then holds a reference to somefunction. You are not creating a new function as you are in the first case.
I think this example may make the difference clear. arguments is an array like object that contains each of the arguments passed to a function.
Try running each of these lines on your favorite browser console.
var somefunction = function() { console.log(arguments); };
Your first example demonstrates defining a named function a that closes around the named function somefunction.
var a = function() { somefunction(); };
Your second example makes a reference, b, directly to somefunction. This makes invoking b the same as invoking somefunction.
var b = somefunction;
Now if you call each of these a and b with some arguments you will see the difference.
=> a('a', 1);
[]
=> b('a', 1);
['a', 1]
In the first case the arguments object is empty. That's because the arguments that were passed to a were not forwarded onto somefunction.
In the second case the arguments are available to somefunction, because some function is being called directly.
Here is how you could redefine a so that it were functionally equivalent using apply
var a = function() { somefunction.apply(this, arguments); }
Running this at your console prints the argument array.
=> a('a', 1);
['a', 1]
var a = function(){
somefunction();
}
Is an Anonymous Function attributed to a variable.
somefunction :function() {
alert("hello");
}
Is an declaration of a function throungh the Object Literal notation.
The diference are shown when you are creating an object. The anonymous function are not acessible as a "public" method, instead in the Object Literal notation, that are acessible from outside.
As Douglas Crockford said, in JS the Good Parts, the first declaration are just a function and the second one could be a method.
In the first case, you are creating a function which calls someFunction(), then you assign that function to a, so now calling a() calls an anonymous function which in turn calls someFunction().
In the second case, a and someFunction become the exact same thing, calling a() is the same as calling someFunction().
The way you're setting var a by accessing the function is clearly out of scope.
So I suspect you have a typo : instead of = :
var somefunction = function() {
alert("hello");
};
somefunction(); // hello
...Now that your first and second makes sense with the code above:
Anonymous Function stored in variable:
var a = function(){
alert('Hey');
somefunction();
};
a(); // Hey // hello
Variable as Function Reference
var a = somefunction;
a(); // hello
In the other case than:
var objLiteral = {
somefunction : function() {
alert("hello");
}
};
var a = objLiteral.somefunction;
a(); // hello
Following are two ways to define BW.Timer. Can someone tell me what the difference is? I am not certain the first is even valid, but if it is valid, what is different about using the myfunc=(function(){}()) syntax?
BW.Timer = (function () {
return {
Add: function (o) {
alert(o);
},
Remove: function (o) {
alert(o);
}
};
} ());
And...
BW.Timer = function () {
return {
Add: function (o) {
alert(o);
},
Remove: function (o) {
alert(o);
}
};
};
The first is the return-value of the immediately-invoked function. The second is a function. It essentially comes down to what the difference is between these:
var f = (function() { return 0; })();
var f = function() { return 0; };
Since the first function is called immediately, the value of 0 is given to the variable f. The first f is not a function. However, the second f we must call in order to get the value:
f(); // 0
It follows that in your example, the first BW.Timer is the object literal itself and the second is a function returning an object literal. You must call the function in order to get to the object:
BW.Timer().Add(x);
Why use the first then?
You might ask yourself why one would use a syntax like a = (function() { return {}; })() instead of a = {}, but there's a good reason. An IIFE (Immeditately-Invoked Function Expression), unlike a regular function allows the emulation of static variables (variables that maintain their value through a single instance). For example:
var module = (function() {
var x = 0;
return { get: function() { return x },
set: function(n) { x = n }
};
})();
The above a text-book example of the Module Pattern. Since the function is called right away, the variable x is instantiated and the return value (the object) is given to module. There's no way we can get to x other than by using the get and set methods provided for us. Therefore, x is static, meaning its variable won't be overridden each time you use module.
module.set(5);
module.get(); // 5
On the other hand, let's see an example where module is declared as a function instead:
// assume module was made as a function
module().set(5);
module().get(); // 0
When we call module() the x variable is overridden each time. So we're effectively using different instances of module and x each time we call module.
The difference is rather large.
In the first case, BW.Timer is executed when it is first encountered, and that is the static version assigned to BW.Timer. In that instance, BW.Timer.Add(1) may be used. Each call to BW.Timer will be the same object.
In the second case, BW.Timer is not executed when first encountered, and instead is a function referece which must be invoked BW.Timer(). For Add to be used, this must be the case BW.Timer().Add(1). Also, you can issue var timer = new BM.Timer();. Each instance of BW.Timer() will be unique here.
In the first example BW.Timer references an object that the self-executing function returns, while in the second example it references a function object, in other words it's a function that can be executed BW.Timer().