【问题标题】:JavaScript - Getter/Setter in Objects's Prototype is not working. Getter returns last elementJavaScript - 对象原型中的 Getter/Setter 不起作用。 Getter 返回最后一个元素
【发布时间】:2013-01-08 06:47:53
【问题描述】:

我是 JavaScript 新手。在使用给定的javascript时,我期望输出值为“123”; “测试1”; “456”和“test2”,因为有两个实例。

但是返回的值是 "456";"test2"; “456”和“test2”。

如果我将设置器更改为处理“this”(目前已在代码中删除),问题就解决了。我无法理解为什么原型对象的行为不同。

我不想用这个声明变量,因为我希望变量是私有的,只能通过 getter/setters 方法访问。

<html>
<head>
<script type="text/javascript">

function Test(){
    var name;
    var id;


    Test.prototype.setId = function(newId){
        id = newId; 
    }

    //this.id = function(newId){
    Test.prototype.getId = function(newId){
        return  id;
    }


    Test.prototype.setName = function(newName){
        name = newName; 
    }

    //this.getName = function(newGuid){
    Test.prototype.getName = function(newGuid){
        return name;    
    }


}



function callme(){
    var instance1 = new Test();
    instance1.setId("123");
    instance1.setName("test1");
    var instance2 = new Test();
    instance2.setId("456");
    instance2.setName("test2");
    alert(instance1.getId());
    alert(instance1.getName());
    alert(instance2.getId());
    alert(instance2.getName());
}


</script>
</head>

<body>
<button onclick='callme()'> Test </button>
</body>
</html>

根据下面给出的 Matt 的建议,我已经更改了我的代码。但是代码不适用于继承。我修改了代码如下。当前实现创建派生类型的对象并尝试调用基类的方法。

<html>
<head>
<script type="text/javascript">

(function () {
    var stores = [];
    var counter = 0;
    Test = function () {
        this.storeId = stores.length;
        stores.push({});
    }

    Test.prototype.setGuid = function (newId) {
        stores[this.storeId].id = newId;
    }
    Test.prototype.getGuid = function (newId) {
        return stores[this.storeId].id;
    }
    Test.prototype.setName = function (newName) {
        stores[this.storeId].name = newName;
    }
    Test.prototype.getName = function (newGuid) {
        return stores[this.storeId].name;
    }
})();

Derived.prototype = new Test();
Derived.prototype.constructor = Derived

function Derived(){
    Test();//call to base class
    //some additional method
}


function callme(){
    var instance1 = new Derived();
    instance1.setGuid("123");
    instance1.setName("test1");

    var instance2 = new Derived();
    instance2.setGuid("456");
    instance2.setName("test2");

    alert(instance1.getName());
    alert(instance1.getGuid());

    alert(instance2.getName());
    alert(instance2.getGuid());



}


</script>
</head>

<body>
<button onclick='callme()'> Test </button>
</body>
</html>

其次,当变量被清除(超出范围)时,我不确定是否要从 stores 变量中清除内存。

【问题讨论】:

    标签: javascript prototype getter-setter last-modified


    【解决方案1】:

    我喜欢马特的方法。如果存储的数量变化很大,您可以使用对象而不是数组,并使用某种删除存储[this.storeID] 的 dispose 方法。也许 Javascript 中有一种方法可以在垃圾收集期间自动调用这样的方法/函数,或者当对象离开可用范围时?否则你必须在为时已晚之前调用它。

    继承问题可能是由错误实现的继承引起的。

    【讨论】:

      【解决方案2】:

      每次创建新实例时都在设置原型方法 - 因此变量引用将在实例之间共享。

      按照dystroy的建议使用this.variableName或使用this.setName = function(newName)。 (对变量使用 this 更好,因为它不会为每个对象实例复制函数。)

      但如果您真的不想公开变量,请使用:

      function Test(){
          var name;
          var id;
      
          this.setId = function(newId){
              id = newId; 
          }
      
          this.getId = function(newId){
              return  id;
          }
      
          this.setName = function(newName){
              name = newName; 
          }
      
          this.getName = function(newGuid){
              return name;    
          }
      }
      

      在不直接公开变量的情况下共享原型函数的解决方法是:

      (function () {
          var stores = [];
          var counter = 0;
          window.Test = function () {
              this.storeId = stores.length;
              stores.push({});
          }
      
          Test.prototype.setId = function (newId) {
              stores[this.storeId].id = newId;
          }
          Test.prototype.getId = function (newId) {
              return stores[this.storeId].id;
          }
          Test.prototype.setName = function (newName) {
              stores[this.storeId].name = newName;
          }
          Test.prototype.getName = function (newGuid) {
              return stores[this.storeId].name;
          }
      })();
      

      说明:代码被包裹在IIFE 中,确保不能从该函数外部访问变量。在 IIFE 中,我们为我们的对象实例创建了一个存储列表。然后我们定义 Test 类并将函数添加到原型中。

      每当创建新实例时,我们都会创建一个新商店并将其附加到商店列表中。我们还将storeId 添加到实例中,以便我们可以访问实例存储中的值。外部函数可以访问 storeId,但可以从 store 本身获取任何数据。

      stores[this.storeId] 总是为我们的对象实例获取存储,然后我们使用类似于this

      【讨论】:

      • 我不想使用这个,否则变量将被公开。我希望变量是私有的。
      • @user2007533 我的解决方案没有公开变量,我添加了一个代码示例。
      • 感谢您的建议。但是,如果我按照您的建议使用这些函数,则测试类的所有实例都将具有这些方法。它会使所有实例变量膨胀。我希望所有方法都在 Prototype 类中,并且变量是私有的。
      • @user2007533 我认为内存不会成为问题,除非您拥有大量此类对象(数万个)。原型方法在所有对象实例之间共享 - 因此它们将无法引用除 this 之外的不同变量。我有一个解决方法的想法,我将添加到答案中。
      • 感谢您的解决方法。它运作良好。但是作为 JavaScript 的初学者,我无法完全理解代码。 :(。你能解释一下吗?你能不能从设计的角度告诉你,如何让所有的 getter 使用 'this' 和 setter 和其他方法作为原型方法。
      【解决方案3】:

      您的属性是全球性的。您必须使用this 来引用实例的属性。

      像这样修复你的代码:

      function Test(){
          this.name =''; // this only to show that the property exist,
                         //  it doesn't change the behavior as you set it later
          this.id='';
      }
      
      Test.prototype.setId = function(newId){
          this.id = newId; 
      }
      
      Test.prototype.getId = function(){
          return this.id;
      }
      
      
      Test.prototype.setName = function(newName){
          this.name = newName; 
      }
      
      Test.prototype.getName = function(){
          return this.name;    
      }
      

      我修复了一些其他问题,其中包括你不应该在 getX 中声明一个参数,因为你不需要它。

      【讨论】:

      • 感谢您的快速回复。我不想使用它,因为我希望变量名和 id 是私有的。否则即使没有 getter/setter 也可以访问这些变量。
      猜你喜欢
      • 2011-08-27
      • 2017-09-26
      • 2012-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      相关资源
      最近更新 更多