繁体   English   中英

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

[英]Inner function cannot access outer function variable after being changed

是的,这个问题与内部函数无法访问外部函数变量类似。 但这不一样。 让我困惑的是“被改变后”。 下面的代码可能更直观。

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的值?

希望我能得到一些基本的答案,谢谢=)

您正在创建一个新的关闭。 返回的函数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

它实际上是另一个seq变量。 第一次运行set_seq时, seq变量已绑定到它,它不会直接从函数声明中读取它。

换句话说,当您定义原始函数时,将返回带有set_prefixset_seqgensym的对象,并且这些函数中的每个函数都已经引用了seq变量,该变量在函数的闭包中定义。 将新函数分配给返回的对象时,它没有原始seq变量的概念。

正如@ 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'

尝试使用var seq = 0作为全局变量。 即无变种。

var prefix = ''; // scope :- local

seq = 0; // scope :- global

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM