4

Where is the data supplied by the argument being stored? Is a var first being created implicitly?

function Student(first){
   this.getFirst = function(){
     return first;
   }
}

Tested with:

var myStudent = new Student("ross");

console.log(myStudent); // Student { getFirst=function() }

console.log(myStudent.getFirst()); // ross

console.log(first); // reference error, first not defined

console.log(myStudent.first); // undefined

for(var x in myStudent){ console.log(x); } // getFirst

My second question is if I understand these correctly:

What happens with "var" variables inside a JavaScript Constructor?

“var” variables, "this" variables and "global" variables - inside a JavaScript Constructor

...is the getFirst function creates a closure and saves the state of the constructor's parameter value, if I use a var first in the constructor body is it okay to think of that as 'encapsulation'? Additionally, any inner function saves all the parameter values in a "closure state" or just the one's referenced by the inner function?

Thank you very much for your thoughts. This is my first question on S.O. but use the site almost daily as a reference, so thank you for that. My programming knowledge is limited so pardon if I've used crappy terms, happy to clarify where needed.

Community
  • 1
  • 1
ross studtman
  • 936
  • 1
  • 8
  • 22
  • The `var` keyword inside a function "creates" a variable with the *same scoping rules* as the parameter [variables] of the function; the converse is also true. –  Oct 31 '12 at 03:00

2 Answers2

4

The first parameter is stored locally to the function that is your constructor, so anywhere inside Student() it will be in scope.

More interestingly, the the anonymous inner function that you're assigning to this.getFirst is closing over that value. Because of that, the inner function maintains a reference to the first variable even after the constructor is finished executing.

This works for regular functions too, not just constructors:

function makeCounter() {
   var count = 1;
   return function() { return count++; };
}

var counter = makeCounter();
console.log(counter());  // 1
console.log(counter());  // 2
console.log(counter());  // 3

When used the right way, this approach can be used to achieve "private" variables in JavaScript, in the sense that the values captured in the closure are inaccessible from the outside.

Because of that, it turns out not to matter whether a closure captures all the variables in its scope or just the ones it uses, since you can't "reach inside" to those closed-over variables anyway. (Though in practice generally only the used values are captured, so that the runtime can garbage collect the rest, as they're unneeded.)

dfreeman
  • 2,834
  • 2
  • 20
  • 24
  • So would it be a legitimate coding strategy to define javascript constructors without explicitly including in the body of the constructor any attributes (that have getters/setters)? If done this way, is memory used any differently than if the getter/setters had assigned to a declared attribute? Will the closure be made regardless? If so, maybe explicit declaration of attributes is wasteful? – ross studtman Oct 31 '12 at 15:14
  • Whether you refer to an object via its name as a function parameter or as a local var within the function, any closures you have are just keeping a reference to that same object, not making a copy of it. Because of that, it really doesn't matter which way you go. – dfreeman Oct 31 '12 at 20:08
1

To get a little further into what you're asking, it's not about creating a var, but rather in your instance the function also keeps the arguments array.

Your functions can happily create closures over both.
By returning functions from your function, those returned functions (or objects with functions as methods) have access to any and all vars and arguments, as long as you don't overwrite those functions.

The magic of closures.

Norguard
  • 26,167
  • 5
  • 41
  • 49
  • This is interesting: every parameter sent to the constructor, which comprises the *arguments* collection, is kept ...sorry for the term: "alive" because the closure references one of them? Or is the arguments collection pared down somehow to only those elements that have references to them? – ross studtman Oct 31 '12 at 15:26
  • 1
    That's going a little too far into "it depends" territory. What you're actually referring to now is garbage-collection. When a function returns, its internals are no longer needed, so the whole thing gets marked for garbage-collection. If there's still a living-reference to one of those vars/arguments/functions, then it can't be collected. Whether this means that those saved vars are kept in memory and everything else is wiped, or if the whole scope of the function is maintained in memory is up to the JS engine in question. – Norguard Oct 31 '12 at 16:40