操作闭包中定义的变量

6

假设我有一个定义和实例化的JavaScript类,如下:

Demo = function() { 
  var abc = "foo";

  return {
    get test() { return abc; }
  }
}

obj = Demo();
obj.test  // evaluates to "foo"

仅仅面对这个演示实例obj,我能否改变属于这个对象的变量abc的值,该变量是在构造函数引入的闭包中定义的?

3个回答

3

var abc 在 Demo 的作用域之外是无法直接访问的。

如果您想要在该作用域之外改变它,您需要添加一个方法来进行设置。

Demo = function() { 
  var abc = "foo";

  return {
    get test() { return abc; }
  }

  this.setTest(a) {abc = a;}
}

var obj = new Demo();
obj.setTest("fun");

请参考此前的讨论,了解可以使用哪些类型的访问器。

这很明显,但我宁愿不改变这个类。 - Niklas B.
然而因为我没有明确说明,你的建议对其他人可能会有帮助,所以我给你加了一个赞。 - Niklas B.
1
您正在使用一种设计模式,使abc成为“私有”变量。请参阅此线程https://dev59.com/plrUa4cB1Zd3GeqPmbjp以进行进一步讨论,但是私有就是私有。它在不更改类的情况下在该范围之外是不可用的。 - jfriend00
1
是的,我现在明白了。我只是认为可能会有一些诀窍,就像当你想要访问Ruby或Python中的私有成员时一样(我从未涉足过严肃的JavaScript编程 :))。 - Niklas B.
唯一的技巧就是创建一个访问器方法。只要你创建了一个暴露出私有属性的访问器方法,private 属性就不再是私有的了。如果你不想它们是私有的,可以使对象拥有公共属性,在函数的范围之外能够自由读取或赋值。但是这样做需要修改类并重新定义 abc - jfriend00
我想操作的是 env.js 文件中的 window.location 对象。我希望这可以在不修改库代码的情况下实现,但似乎宇宙与我作对。 - Niklas B.

2

不是。这是闭包的基本用途之一——定义私有、无法访问的变量。它们可以被检索,但除非有一个“setter”函数,否则它们不能被修改。


谢谢。我会接受jfriend00的答案,因为它为其他有可能更改类接口的用户提供了一些帮助。 - Niklas B.

0

我认为你有点困惑了。如果你像使用一个类一样使用Demo,你不应该像调用一个函数一样调用它,而是像实例化一个类一样。

当与实例化一起使用时,你肯定可以这样做:

function Demo(){
  var abc = "some value";

  this.setAbc = function(val){
    return abc = val;
  }

  this.getAbc = function(){
    return abc;
  }
}

var d = new Demo();
d.getAbc()   // => 'some value';
d.setAbc('another value');
d.getAbc()   // => 'another value';

在“构造函数”内定义的这些类型的函数被称为特权函数。它们可以访问公共变量(即在原型上定义的变量)和私有变量。阅读this以了解“类”的公共/私有/特权成员的详细信息。

请注意,如果您只是执行以下操作:

var d = Demo();

你并没有得到 Demo 的实例,你只是得到了它返回的内容。在我的情况下是 undefined

编辑

再次阅读您的帖子后,快速答案就是不行,至少不是使用您特定的定义方式,您需要做类似于我所做的事情。

或者,如果您坚持使用您的范例:

function Demo(){
  var abc = "some value";

  return {
    get test(){ return abc; },
    set test(val){ abc = val; }
  }
}

它为我返回一个对象,这是env.js定义Location类的方式,所以可能是一种ECMAScript形式,至少被Rhino和V8(我使用的解释器)理解。在这种情况下,{ ... }创建一个对象,而get test() { }定义了一个属性。因此,Demo函数构造并返回一个具有属性test的对象。 - Niklas B.
啊,抱歉,没有注意到返回对象的模式。再次强调,如果不修改你的“类”,就无法设置变量。我更新了我的答案以反映这一点。 - brad

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