Javascript变量 - Getter问题

时间:2012-07-24 17:47:32

标签: javascript variables private getter

我想出了下面的情况:

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”,即使我为其分配了新值?
  3. 有什么想法吗?

    这是一个让事情变得更轻松的小事。

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

3 个答案:

答案 0 :(得分:6)

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

getter仍然引用值为Fido的(private)变量。

如果您想允许消费者更改私有变量,您还需要一个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"

答案 1 :(得分: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; }

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

答案 2 :(得分:1)

构造函数中的

var namesomeObj.name永远不会是同一个东西。 2个不同的值,可以设置为2个不同的东西。相反,你需要一个像你的getter一样工作的setter函数:

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

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