是的,这个问题与Inner function cannot access outer functions variable类似。但它不是同一个。令我感到困惑的是"在被改变后#34;。下面的代码可能更直观。
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'
所以这就是我想弄清楚的 - 为什么重写的set_seq
方法没有改变外部函数中私有变量seq
的值?
希望我能得到一些必要的答案,谢谢=)
答案 0 :(得分:4)
您正在创建一个新的闭包。返回的函数seqer.set_seq是一个可以访问私有变量seq的闭包。但新定义的seqer.set_seq正在创建一个无法访问私有变量的新闭包,而是创建一个新的全局变量window.seq
试一试:
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
答案 1 :(得分:2)
它实际上是另一个seq
变量。当您第一次运行set_seq
时,seq
变量已经被绑定到它,它不会直接从函数声明中读取它。
换句话说,当您定义原始函数时,会返回一个set_prefix
,set_seq
和gensym
的对象,并且每个函数都已经引用了{{ 1}}变量,在函数的闭包中定义。为返回的对象分配新函数时,它没有原始seq
变量的概念。
答案 2 :(得分:1)
正如@ devnull69所提到的,你创建了一个闭包,你的seq正在寻找全局。如果你想在事后修改你的方法,也许看一下原型。
// 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'
答案 3 :(得分:-1)
尝试将var seq = 0用作全局。即没有var。
var prefix = ''; // scope :- local
seq = 0; // scope :- global