JavaScript 动态获取/设置私有属性的 getter/setter 方法

5

我希望能够动态地创建getter/setter方法以检索私有属性。

以下是我的实现方式:

首先,我创建了一个类:

function winClass (posX, posY, w, h) {
  var x = posX || 0;
  var y = posY || 0;
  var width = w || 0;
  var height = h || 0;
}

然后我使用以下getter/setter方法扩展了winClass:

winClass.prototype.getX = function () {
  return x;
}

winClass.prototype.setX = function (val) {
  x = val;
}

然后我进行了测试:

var win1 = new winClass (10, 10, 100, 100);
document.write (win1.getX ());

但是当我尝试设置'getX'方法时,会出现以下错误:'x未定义'。这很有道理,因为'x'不在winClass范围内,但我不知道如何为私有变量动态设置getter/setter方法。有什么想法吗?

看看这个链接,它解释了如何在JavaScript中编写C#风格的getter和setter。非常酷。 - Micha Roon
1个回答

13

getter/setter 方法必须在能看到私有变量的作用域内,而唯一能够看到这些变量的作用域是构造函数的内部。 这就是为什么这些变量实际上是私有的原因。 因此,要为它们创建 getter/setter,必须将函数放在可以看到它们的作用域中。以下代码可行:

function winClass (posX, posY, w, h) {
  var x = posX || 0;
  var y = posY || 0;
  var width = w || 0;
  var height = h || 0;

  this.getX = function() {return(x);}
  this.setX = function(newX) {x = newX;}
}

var win1 = new winClass (10, 10, 100, 100);
alert(win1.getX());   // alerts 10

你可以在这里看到它的运作效果:http://jsfiddle.net/jfriend00/hYps2/

如果你想要一个通用的私有变量 getter/setter,你可以像这样做:

function winClass (posX, posY, w, h) {
  var privates = {};
  privates.x = posX || 0;
  privates.y = posY || 0;
  privates.width = w || 0;
  privates.height = h || 0;

  this.get = function(item) {return(privates[item]);}
  this.set = function(item, val) {privates[item] = val;}
}

var win2 = new winClass(10,10,100,100);
alert(win2.get("x"));    // alerts 10

如果你想绕过这些私有变量的限制,虽然这对我来说毫无意义(因为你可以把它们作为标准实例变量处理),你可以像这样操作:

function winClass (posX, posY, w, h) {
  var privates = {};
  privates.x = posX || 0;
  privates.y = posY || 0;
  privates.width = w || 0;
  privates.height = h || 0;

  this.getPrivates = function() {return(privates);}
}

winClass.prototype.getX = function() {
    return(this.getPrivates().x);
}

winClass.prototype.setX = function(newX) {
    this.getPrivates().x = newX;
}

这里有一个例子:http://jsfiddle.net/jfriend00/EKHFh/

当然,这会破坏变量的私有性质,所以用这种方法没有任何意义,因为将它们设置为常规实例变量会更容易,且具有相同的访问控制。

还有一种正常的实例变量方法,可以自由地向原型添加访问器方法,但是变量不是私有的。

function winClass (posX, posY, w, h) {
  this.x = posX || 0;
  this.y = posY || 0;
  this.width = w || 0;
  this.height = h || 0;
}

winClass.prototype.getX = function() {
    return(this.x);
}

winClass.prototype.setX = function(newX) {
    this.x = newX;
}

1
正如我之前所说,这些是私有变量,你唯一可以访问它们的方式是在构造函数内部。任何允许你从构造函数外部访问它们的方式都会破坏它们的私有性质,你可能还不如将它们变成明显的实例变量。选择你想要的特征,然后使用那种类型的变量。私有就是私有。你可以绕过它,但那样它们就不再是私有的了。我会再添加一个绕过私有的方法,但实际上没有必要,因为它们应该变成实例变量。 - jfriend00
2
@Ed Heal - 你需要更加赞赏原型继承。JavaScript的原型概念来自于Self语言,除了语法外,它并不是一个假象。 - hugomg
非常好的答案,让我说。 - NiKo
1
@EdHeal(今天偶然发现了这个 :) 它既不是欺骗也不是假的,只是不像你习惯的面向对象编程(或者一百万年前的那种)。以Self为例,它也是一种原型式面向对象语言。没有任何非面向对象的东西。 - Dave Newton
@DaveNewton - 猜测你喜欢考古学 :-) - Ed Heal
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接