0

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>
3
  • Nevermind this is incorrect. Commented Nov 26, 2013 at 2:10
  • 5
    I don't think closures are your problem. You should read more about prototypical inheritance and object creation patterns in JavaScript. Commented Nov 26, 2013 at 2:12
  • Variables in a closure scope are not accessible like that. They can only be accessed in the body of the function. Sometimes this is used to create private members (I prefer to use _private for various reasons) but in order to understand that you have to understand how functions can be used as a constructor. Maybe this answer can help you there: stackoverflow.com/a/16063711/1641941 Commented Nov 26, 2013 at 3:37

2 Answers 2

1

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');
Sign up to request clarification or add additional context in comments.

2 Comments

Or the OP could do obj1.prototype.firstname. :-/
@RobG I think firstname is more instance specific and would probably be shadowed as soon as you create an instance. Not sure what the OP is trying to acheave with this pattern but it looks like another way to avoid the new keyword. Making constructor functions and prototype that are already confusing enough into something that'll make your head spin.
0

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).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.