user1050619
user1050619

Reputation: 20916

Understanding JavaScript closure functions

I'm a newbie to Javascript and have question on closure functions.

In the below code, I'm creating a closure function and setting a new property firstname for the same function. I want to identify the property - firstname - of my function that is created and use the code - console.log(obj1.firstname); to display it.

But for some reason its displaying as undefined. Please let me know what is the problem.

<html>
  <head>
    <script>
      outerfunction = function(firstname,lastname) {
        var innerfunction = function (sex) {
        console.log(firstname);
        console.log(lastname);
        console.log(sex)
        }

        console.log('Initialize');
        innerfunction.prototype.firstname = firstname;
        return innerfunction;
      }

      obj1 = outerfunction('Bob','Mcdonald');
      console.log(obj1.firstname);
      obj2 = obj1('Male');

      obj1 = outerfunction('Lucy','Mary');
      obj1('Female');

    </script>

  </head>
  <body>
    This is the body
  </body>
</html>

Upvotes: 0

Views: 98

Answers (2)

RobG
RobG

Reputation: 147563

Just comments:

>  outerfunction = function

Variables should always be declared, particularly global variables so that they do not clash with DOM elements with the same name or ID (the variable will take precedence). Once you declare variables, then there is no point in assigning a function expression where a declaration will do (if nothing else, it's less to type but also makes the function available before any code is executed, rather than at the point the assignment is made). So:

function outerfunction(firstname,lastname) { 

Items in the formal parameter list (firstname, lastname) are effectively declared local variables. So for innerfunction:

  function innerfunction(sex) {
    console.log(firstname);
    console.log(lastname);
    console.log(sex)

This function has a closure to firstname and lastname of outerfunction.

>         innerfunction.prototype.firstname = firstname;

This is only useful if innerfunction is a constructor, and only if you want instances to inherit the firstname property. Functions do not inherit from their public prototype but from their private [[Prototype]], which is the public prototype of their constructor at the time they were constructed.

> obj1 = outerfunction('Bob','Mcdonald');

This returns an "instance" of innerfunction which has closures to firstname and lastname.

> console.log(obj1.firstname);

But the firstname property is on obj1.prototype (because that's where it was assigned), so is not found (check obj1.prototype.firstname).

Part of your confusion may be over the difference between identifier resolution on the scope chain (i.e. the variables firstname and lastname) and object property resolution on the object and its [[Prototype]] chain (i.e. inheritance and innerfunction.protoype.firstname).

Upvotes: 0

Jason
Jason

Reputation: 1959

The problem is with your use of prototype. If you do innerfunction.firstname = firstname; that should fix the undefined problem.

outerfunction = function(firstname,lastname) {
  var innerfunction = function (sex) {
    console.log(firstname);
    console.log(lastname);
    console.log(sex)
  }

  console.log('Initialize');
  innerfunction.firstname = firstname;
  return innerfunction;
}

obj1 = outerfunction('Bob','Mcdonald');
console.log(obj1.firstname);
obj2 = obj1('Male');

obj1 = outerfunction('Lucy','Mary');
obj1('Female');

Upvotes: 1

Related Questions