I'm learning JavaScript, coming from Ruby, have done some stuff in C as well. One example in my reading is:
function letCounter() {
let counter = 0;
return () => ++counter;
}
and is compared to
function thisCounter() {
this._count = 0;
}
thisCounter.prototype.fire = function() {
this._count ++;
return this._count;
}
In the first example, the count is NOT accessible on an instance of letCounter:
let let_counter_ins = letCounter();
let_counter_ins.counter // <- undefined
while in the second, count, ~I think~, is an attribute of all instances of the function itself?
let this_counter_ins = new thisCounter();
this_counter_ins.count // <- 0
Seems like a function in JavaScript can have 'state' (calls to console.log(let_counter_ins()) will continuously increment a counter, as opposed to it starting over at 0). But also this 'state', set with let is somehow different than a 'state' set with this? Seems like instances of both letCounter and thisCounter are keeping track of some counter, but how it is accessible is different? Trying to understand what the difference is between setting function attributes with this vs let and why one of them is available externally.
In the first code, a local variable
counteris initialized, and the returned function closes over the variable (in a "closure"). The value only exists in the local scope of the function - in a Lexical Environment that, once the function finishes, is only referenceable via the() => ++counter. There's no way to directly observe the contents of a closure, other than by the methods that the closure may (or may not) have returned or use that deliberately expose its contents.Every call of
letCounterwill result in a new binding forcounterbeing created, a new Lexical Environment for it, and a new closure, so separate calls ofletCounterwill result in separate counts being kept track of.In the second code, with
this,counteris not a local variable, but a normal property of the instance object. Object properties are completely public (with the exception of the extremely new#private member syntax I won't get into), so anything, includingthisCounter.prototype.fireand external code can accessthis.counter(wherethisreferences the instance) orthis_counter_ins.count(wherethis_counter_insreferences the instance) and get the current value on the object.