1

我想出了以下情况:

function Dog () {
    "use strict";
    this.age = 1;
    var name = "Fido";
    this.getName = function () { return name; }
}

现在我正在创建“Dog”类的一个新实例并打印变量的值。

var d = new Dog;
document.write('<strong>Dog age:</strong> ' +d.age); \\Outputs "1" as expected
document.write('<br/>');
document.write('<strong>Dog name:</strong> ' +d.name); \\Outputs "undefined" as expected, 'cause it's a private variable.
document.write('<br/>');
document.write('<strong>Get Dog name:</strong> ' +d.getName()); \\Outputs "Fido", as expected.

但是假设我想改变狗的名字,像这样:

d.name = "Stinky";
document.write('<br/>');
document.write('<strong>Dog name Again:</strong> ' +d.name); 
document.write('<br/>');
document.write('<strong>Get Dog name Again:</strong> ' +d.getName());

基于此,我有几个问题:

  1. 为什么“d.name”没有向我显示“未定义”?“名称”不是私有变量吗?我想你不能改变私有变量的值,对吗?我想知道这个过程是否创建了一个新变量,但这次是一个公共变量,并且具有相同的名称。如果是这样,有没有办法防止每次我尝试分配具有相同名称的新属性时创建新变量?有没有办法抛出“类型错误”或其他东西(嗯,这是我所期望的)。
  2. 最后:为什么“getName”会打印原始值“Fido”,即使我为它分配了一个新值?

有任何想法吗?

这是一个让事情变得更容易的fid。

http://fiddle.jshell.net/yZpfg/2/

4

3 回答 3

6

d.name = "Stinky";正在向d对象添加一个新的(公共)属性,即instanceOf Dog.

getter 仍然使用 value 引用(私有)变量Fido

如果您想允许消费者更改私有变量,您还需要一个 setter:

function Dog () {
    "use strict";
    this.age = 1;
    var name = "Fido";
    this.getName = function () { return name; }
    this.setName = function (value) { name = value; }
}

var d = new Dog(); 
d.name; // undefined because there is no name public property
d.getName() // returns the internal private, "Fido"
d.setName('Stinky'); // the internal private is now "Stinky"
于 2012-07-24T17:51:19.253 回答
1

您将局部变量与实例属性混淆了。这些是完全分开的。

1)您设置d.name,一个实例属性,这是您正在调用的,而不是私有变量。

2) Fido 是私有 var 的 valeu,这是你的方法返回的,而不是实例属性,所以方法总是会说 Fido。

您的原始代码应该如下所示:

function Dog () {
    "use strict";
    this.age = 1;
    this.name = "Fido";
}
Dog.prototype.getName = function() { return this.name; }

请注意,我将方法添加到原型中,而不是显式地将其添加到每个实例中。这样,实例就会继承它。这是更好的做法;可重用的代码应该在原型上,并且它比每次都将其添加到每个实例中性能更好。

于 2012-07-24T17:53:03.740 回答
1

var name在您的构造函数中,someObj.name并且永远不会是同一件事。2 个不同的值可以设置为 2 个不同的东西。相反,您需要一个像 getter 一样工作的 setter 函数:

this.setName = function(newName) { name = newName; };

设置与私有变量同名的属性时,无法引发错误。它们是两个完全不同的东西,当设置了一个你甚至可以拦截的属性时没有回调。

于 2012-07-24T17:53:40.090 回答