簡體   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