【问题标题】:Javascript variables - Getter issueJavascript 变量 - Getter 问题
【发布时间】:2012-07-23 02:23:26
【问题描述】:

我想出了以下情况:

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/

【问题讨论】:

  • 它输出undefined只是因为该属性不完全存在于对象上,而不是因为对象上有私有属性
  • 您需要更好地了解closures,然后才能开始了解这里发生了什么。
  • 是时候了解一下getters and setters了。
  • Javascript 没有诸如“公共”或“私有”属性之类的东西。属性始终是公开的。您只能在闭包的帮助下实现某种“伪”隐私,该闭包利用 JS 的函数范围(您的变量名就是这种情况)。

标签: javascript variables private getter


【解决方案1】:

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

getter 仍然引用值为 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"

【讨论】:

  • 为了清楚起见(以防“狗对象”令人困惑),它向d 对象(Dog 的实例)添加了一个新属性。它不会向Dog 本身添加新属性。
  • Javascript 没有诸如“公共”或“私有”属性之类的东西。您只能在闭包的帮助下实现某种“伪”隐私(变量name 就是这种情况)。 (嗯,实际上这应该是对问题的评论......)
  • @Christoph 这是一个作用域,而不是一个闭包,更容易将它们称为“公共”和“私有”。
  • @jbabey 它是一个闭包 - 由于 getter 函数,var name 存在于原始函数的范围之外。唯一的问题是,该变量不再可公开访问。
  • 魔鬼的拥护者:“闭包是通过返回一个函数对象来形成的,该函数对象是在该函数调用的函数调用的执行上下文中创建的,并将对该内部函数的引用分配给另一个对象的属性。” jibbering.com/faq/notes/closures/#clFrmC
【解决方案2】:

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

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

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

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

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

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

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-18
      • 2011-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多