简体   繁体   English

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

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

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? 所以这就是我要弄清楚的原因-为什么重写的set_seq方法没有更改外部函数中私有变量seq的值?

Hope i could get some essential answers, thanks =) 希望我能得到一些基本的答案,谢谢=)

You are creating a new closure. 您正在创建一个新的关闭。 The returned function seqer.set_seq is a closure which can access the private variable seq. 返回的函数seqer.set_seq是一个闭包,可以访问私有变量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 但是新定义的seqer.set_seq正在创建一个无法访问私有变量的新闭包,而是创建了一个新的全局一个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

It's actually another seq variable. 它实际上是另一个seq变量。 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. 第一次运行set_seq时, seq变量已绑定到它,它不会直接从函数声明中读取它。

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. 换句话说,当您定义原始函数时,将返回带有set_prefixset_seqgensym的对象,并且这些函数中的每个函数都已经引用了seq变量,该变量在函数的闭包中定义。 When you assign a new function to the returned object, it does not have the concept of the original seq variable. 将新函数分配给返回的对象时,它没有原始seq变量的概念。

As @devnull69 has mentioned, you have created a closure and your seq is looking on global. 正如@ devnull69所提到的,您已经创建了一个闭包,并且您的seq正在全局查看。 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'

Try using your var seq = 0 as global. 尝试使用var seq = 0作为全局变量。 ie Without var. 即无变种。

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

seq = 0; // scope :- global

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

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