内部函数在更改后无法访问外部函数变量

时间:2016-06-08 07:17:29

标签: javascript

是的,这个问题与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的值?

希望我能得到一些必要的答案,谢谢=)

4 个答案:

答案 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_prefixset_seqgensym的对象,并且每个函数都已经引用了{{ 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