1

这个问题源于我试图解决的关于在 JavaScript 中拥有“私有”实例变量的能力的问题。在我提出问题之前,您可能想阅读此内容。

为了完整起见,在提出问题之前,我已经说明了我的整个问题。我希望这将提供一个完整的示例,说明如何在 JavaScript 中正确实现实例成员和方法,并让任何来到这里的开发人员了解各种实现的陷阱。

考虑以下 JavaScript 对象:

var MessageBox = (function() {
    function MessageBox(message) {
        this.message = message;
    }

    MessageBox.prototype.Show = function() {
        alert(this.message);
    }
})();

该对象是使用 TypeScript 建模的,可以按如下方式使用:

var msg1 = new MessageBox("Hello World");
msg1.Show(); // alerts "Hello World"

var msg2 = new MessageBox("Bye World");
msg2.Show(); // alerts "Bye World"

但我仍然可以调用:

msg1.message; // "Hello World"
msg2.message; // "Bye World"

所以显然this.message不是私人的。

现在考虑以下 JavaScript 对象:

var MessageBox = (function() {
    return function MessageBox(message) {
        var message = message;

        MessageBox.prototype.Show = function() {
            alert(message);
        }
    }
})();

这只是基于 TypeScript 的MessageBox对象的修改版本。

var msg1 = new MessageBox("Hello World");
msg1.Show(); // alerts "Hello World"

var msg2 = new MessageBox("Bye World");
msg2.Show(); // alerts "Bye World"

但是等等……我要扔扳手了!

var msg1 = new MessageBox("Hello World");
var msg2 = new MessageBox("Bye World");
msg2.Show(); // alerts "Bye World"
msg1.Show(); // alerts "Bye World" ... wait, what!?

msg1.message // undefined
msg2.message // undefined

所以我无法再访问消息变量,但现在,每个新实例都会覆盖最后一个实例消息。

请耐心等待,这是要考虑的最后一个 JavaScript 对象:

var MessageBox = (function() {
    return function MessageBox(message) {
        var message = message;

        this.Show = function() {
            alert(message);
        }
    }
}();

上面的对象不再在原型上实现 Show(),所以现在我可以:

var msg1 = new MessageBox("Hello World");
var msg2 = new MessageBox("Bye World");
msg2.Show(); // alerts "Bye World"
msg1.Show(); // alerts "Hello World"

msg1.message // undefined
msg2.message // undefined

伟大的!现在我有了私有变量,它们不会互相覆盖!

所以,最后的问题是:有什么区别:

MessageBox.prototype.Show = function() {
}

this.Show = function() {
}
4

2 回答 2

1

您最终得到的问题有一个简单的答案:在原型上设置函数意味着它可以从任何实例中调用,而在实例上设置函数意味着它只能从该实例中调用。无论哪种方式都可以访问实例上的属性,但是您发现复杂的是,无论哪种方式,函数都只能访问声明它的范围内或包含范围内的局部变量。

以下是提供私有实例和私有原型变量的第一种方法:

var MessageBox = (function() {
    var privateProtoVar = "Hello";

    function MessageBox(message) {
        var privateInstanceVar = message;

        this.instanceMethod = function() {
            alert(privateInstanceVar); // Can access private instance var
            alert(privateProtoVar);    // Can access private prototype var
        }
    }        
    MessageBox.prototype.Show = function() {
        alert(privateProtoVar); // Can access private proto var
        // but can't access privateInstanceVar
    }    
    return MessageBox;
})();

var msg1 = new MessageBox("1"),
    msg2 = new MessageBox("2");

msg1.instanceMethod();  // "1", "Hello"
msg2.instanceMethod();  // "2", "Hello"
msg1.Show();            // "Hello"
msg2.Show();            // "Hello"

该变量privateInstanceVar可由内部函数内声明的任何函数访问MessageBox()不能从函数访问,prototype除非它们在同一范围内声明(我在上面的示例中没有这样做)。

如果您稍后向实例添加其他方法,即在上述结构之外,则这些方法无法访问私有 var,因为它们是在不同的范围内声明的:

msg1.newMethod = function() {
   alert(privateInstanceVar);
}
msg1.newMethod(); // error

演示:http: //jsfiddle.net/SSEga/

于 2013-05-22T09:58:48.433 回答
0

MessageBox.prototype.Show每次Show调用new MessageBox(). _ 因此,每个实例总是Show在相同的范围内共享相同的功能。

于 2013-05-22T09:48:25.243 回答