Reputation: 151
Yes, this question is similar with Inner function cannot access outer functions variable. But it's not the same one. What confused me is "after being changed". Codes below maybe more intuitively.
var serial_maker = function() {
var prefix = '',
seq = 0;
return {
set_prefix: function(p) {
prefix = String(p);
},
set_seq: function(s) {
seq = s;
},
gensym: function() {
var result = prefix + seq;
seq += 1;
return result;
}
};
};
var seqer = serial_maker();
seqer.set_prefix('Q');
seqer.set_seq(1000);
seqer.gensym(); // 'Q1000'
// Rewrite set_seq method
seqer.set_seq = function() {
seq = 2000;
};
seqer.set_seq();
seqer.gensym(); // 'Q1001', which was expected 'Q2000'
So this is what i want to figure out —— why the rewritten set_seq
method didn't change value of the private variable seq
in outer function?
Hope i could get some essential answers, thanks =)
Upvotes: 2
Views: 409
Reputation: 845
As @devnull69 has mentioned, you have created a closure and your seq is looking on global. If you want to modify your methods after the fact, maybe have a look at prototypes.
// Constructor
var Serial_maker = function() {
var prefix = '', seq = 0;
};
// Define the methods
Serial_maker.prototype.set_prefix = function(p) {
prefix = String(p);
};
Serial_maker.prototype.set_seq = function(s) {
seq = s;
}
Serial_maker.prototype.gensym = function() {
var result = prefix + seq;
seq += 1;
return result;
}
// Create the object with new
var seqer = new Serial_maker();
seqer.set_prefix('Q');
seqer.set_seq(1000);
seqer.gensym();
// You can modify the methods on the
// constructor's prototype anywhere in the code
// and it will apply to all objects that were created
// with it.
Serial_maker.prototype.set_seq = function(s) {
seq = 2000;
}
seqer.set_seq();
console.log(seqer.gensym()); // Output is 'Q2000'
Upvotes: 1
Reputation: 1368
Try using your var seq = 0 as global. i.e. Without var.
var prefix = ''; // scope :- local
seq = 0; // scope :- global
Upvotes: -1
Reputation: 16544
You are creating a new closure. The returned function seqer.set_seq is a closure which can access the private variable seq. But the newly defined seqer.set_seq is creating a new closure which cannot access the private variable, instead it creates a new global one window.seq
Try it:
var serial_maker = function() {
var prefix = '',
seq = 0;
return {
set_prefix: function(p) {
prefix = String(p);
},
set_seq: function(s) {
seq = s;
},
gensym: function() {
var result = prefix + seq;
seq += 1;
return result;
}
};
};
var seqer = serial_maker();
seqer.set_prefix('Q');
seqer.set_seq(1000);
seqer.gensym(); // 'Q1000'
// Rewrite set_seq method
seqer.set_seq = function() {
seq = 2000;
};
seqer.set_seq();
seqer.gensym(); // Q1001 is correct!
console.log(window.seq); // 2000
Upvotes: 4
Reputation: 3084
It's actually another seq
variable. When you run set_seq
for the first time, the seq
variable is already bounded to it, it does not read it directly from the function declaration.
In other words, when you define your original function, an object with set_prefix
, set_seq
and gensym
is returned, and each of these function already have a reference to the seq
variable, which is defined in the function's closure. When you assign a new function to the returned object, it does not have the concept of the original seq
variable.
Upvotes: 2