3

i was just watching Douglas Crockford videos and he gave the following exercise to do :

write a function, that when passed a variable, returns a function 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 ?? 

notice the o in send. i have been programming javascript for a while now , but i still don't understand why i get undefined ??

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 come this solution works and mine does't ? i don't see much of a difference in my solution and nothing is obviously wrong that i see. can anybody explain please ?

Ivan
  • 10,052
  • 12
  • 47
  • 78
Alexander Solonik
  • 9,838
  • 18
  • 76
  • 174
  • 1
    Crockford is returning a function that takes no parameters. It gets it's parameters from the outer function. Your function takes parameters which you'd have to supply. – Matt Burland Jul 09 '15 at 16:57

4 Answers4

4

The o in the send(o){ is where you are making a mistake. It is not 'inheriting' the o from the original parent's arguments. Putting it inside that function declaration is creating a new o, inside a new scope of that function.

send isn't passed anything when called, and it returns its first argument so it returns 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 occuring:

function funcky(o) {
   return function send(someArgument){
     return someArgument; //return o; here would find the correct o, the first arg of funcky
   }
}
Alex Mcp
  • 19,037
  • 12
  • 60
  • 93
3

This has to do with the scope of o. When you write:

return function send(o){ // notice the o in send
  return o;
}

The scope of o is local to the function send. But, if you write:

return function send(){
  return o;
}

The scope of o is not local to the function send, but is local to the scope of funcky.

So, when you write function send(o){/*...*/} what is really happening is that o becomes an argument, and would need to be called like this: funcky()(10), but what you want to be able to do is funcky(10)().

EDIT:

For more information about variable scope in JavaScript, please see this very detailed answer on SO.

Community
  • 1
  • 1
Ivan
  • 10,052
  • 12
  • 47
  • 78
2
function funcky(o) {
    return function send(o){ // notice the o in send
      return o;
    }
}

Your inner function's o parameter shadows the o originally passed to funcky. So when you write var x = funcky(3);, x is just a send function which expects a parameter to return, there's nothing captured in a closure.

(In other words, x doesn't have a reference to the original o - 3 in your case, because by the name o it calls the parameter that x itself is called with).

doldt
  • 4,466
  • 3
  • 21
  • 36
2

Because of scope.

The function send overwrites the var o in its 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 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());
Tivie
  • 18,864
  • 5
  • 58
  • 77