Understanding the crockford function that returns a variable value function
I just watched the video by Douglas Crockford and he gave the following exercise:
write a function so that when you pass a variable, a function is returned that, if called, returns the value of the variable.
so I wrote the following function:
function funcky(o) {
return function send(o){ // notice the o in send
return o;
}
}
var x = funcky(3);
console.log(x()); // i get undefined why ??
pay attention to o
in the message. I've been programming javascript for a while, but I still don't understand why I'm getting undefined ??
The crockfords' solution was as follows:
function funcky(o) {
return function send(){
return o;
}
}
var x = funcky(3);
console.log(x()); // get 3 now .
now how does this solution work and mine is wrong? I don't see much difference in my solution and nothing is clearly not the way I see it. Can someone explain please?
source to share
It has to do with volume o
. When you write:
return function send(o){ // notice the o in send
return o;
}
The scope o
is local to the send function. But, if you write:
return function send(){
return o;
}
The scope o is not local to send, but local to funcky.
So when you write function send(o){/*...*/}
, what actually happens is what o
becomes an argument and will need to be called like this: funcky()(10)
but what you want to do is funcky(10)()
.
EDIT:
For more information on variable scoping in JavaScript see this very detailed answer on SO .
source to share
o
o
is the mistake where you make the mistake. It does not "inherit" o
from the original parent arguments. Putting inside this function declaration creates a new one o
inside the new scope of that function.
send
nothing is passed on the call and it returns its first argument for it to return undefined
.
Your code, annotated:
function funcky(o) {
return function send(o){ // DECLARES NEW VARIABLE, happens to have same name
return o; //returns the first argument passed to send
}
}
var x = funcky(3); //nothing is passed to the inner function send
console.log(x()); // undefined due to lack of arguments
A slightly clearer example of what is actually happening:
function funcky(o) {
return function send(someArgument){
return someArgument; //return o; here would find the correct o, the first arg of funcky
}
}
source to share
function funcky(o) {
return function send(o){ // notice the o in send
return o;
}
}
The parameter to your inner function is o
shadowing the o
one originally passed to funcky
. So when you write var x = funcky(3);
x is just a function send
that waits for a parameter to return, nothing is captured in the closure.
(In other words, x has no reference to the original o
- 3 in your case, because by the name o, it calls the parameter that x itself is called with).
source to share
Because of the volume.
The send function overwrites var o in the inner scope.
function funcky(o) {
// o here is whatever you passed in funcky
return function send(o){
// now o here is whatever you pass in send
// since you didn't pass anything the result is undefined
return o;
}
}
Check out this other example
function funcky(o) {
return function send(a){
console.log(a);
console.log(o); // this o is the parent o
return o;
}
}
var x = funcky(3);
console.log(x());
source to share