【问题标题】:Javascript: Internal array is not reset to outer objectsJavascript:内部数组未重置为外部对象
【发布时间】:2014-05-29 22:54:01
【问题描述】:

如何以正确的方式授予对对象内部属性的访问权限?这就是破坏我的应用程序的原因:

我有一个处理数组的对象(这里简化了):

function ListManager() {
    var list = [],
        add = function (element) {
            list.push(element);
        },
        clear = function () {
            list = [];
        };

    return {
        add: add,
        clear: clear,
        list : list
    };
};

但是我在使用它时得到了这个:

var manager = new ListManager();
manager.add("something");
manager.clear();
console.log(manager.list.length); // <= outputs "1"!

单步执行代码显示,在 clear 方法中,list 变成了一个新数组。但是从ListManager 之外的列表没有被清除。

我做错了什么?

【问题讨论】:

  • 你需要在 clear 方法中使用this.list
  • 在返回列表属性的列表时,我认为它传递的是值而不是引用,这就是你得到的值!!
  • 确实是按引用/按值的问题。
  • 把这个标记为 dup 的你们对什么是重复有一种奇怪的感觉。仅仅因为在另一个答案中讨论了此解决方案中涉及的概念并不足以使其重复。这里的答案更有价值,因为它们为这个问题提供了具体的解决方案,而你标记为重复的那个没有。根据我们的定义,今天提出的几乎每一个问题都应该与某事重复,因为当您了解今天所有问题的根源时,可能很少有以前没有讨论过的实际新问题。
  • 最重要的是,您选择重复的问题是关于将参数传递给与该问题的解决方案无关的函数 - 这个问题涉及对分配的错误理解,而不是将参数传递给函数。我正在投票重新开放。

标签: javascript oop scope


【解决方案1】:

这是因为clear 设置了var list 的值,而不是ListManager() 返回的对象上的.list。您可以改用this

function ListManager() {
    var list = [],
        add = function (element) {
            this.list.push(element);
        },
        clear = function () {
            this.list = [];
        };

    return {
        add: add,
        clear: clear,
        list : list
    };
}

【讨论】:

  • 在这种情况下使用var list = [] 有什么意义?您应该在返回的对象中只包含 list: [] 而根本没有局部变量。就个人而言,我不喜欢整个设计模式。既然所有内容都打算在这里公开,为什么不分配所有方法,如this.add = function() {}?它更简单。
  • @jfriend00 当然,我们也可以将var addvar list 内联到对象中。我只是说明了 OP 需要进行的关键更改才能使其正常工作。
  • 好的,很公平。我添加了自己的答案,提供了更简单的代码版本。
【解决方案2】:

使用您当前的结构,您可以:

function ListManager() {
    var list = [],
        add = function (element) {
            list.push(element);
        },
        clear = function () {
            list = [];
        };
        getList=function(){
            return list;
        }


    return {
        add: add,
        clear: clear,
        list : list,
        getList: getList
    };
};

var manager = new ListManager();
manager.add("something");
console.log(manager.getList()); // ["something"]
manager.clear();
console.log(manager.getList()); // []

【讨论】:

    【解决方案3】:
        function ListManager() {
        var list = [],
            add = function (element) {
                this.list.push(element);
            },
            clear = function () {
                this.list = [];
            };
    
        return {
            add: add,
            clear: clear,
            list : list
        };
    };
    
    var manager = new ListManager();
    manager.add("something");
    manager.clear();
    console.log(manager.list.length); // <= now outputs "0"!
    

    【讨论】:

      【解决方案4】:

      正如已经解释的那样,您的问题是当您执行list = [] 时,您正在更改局部变量list,但您并没有更改this.list,因为它们是两个独立的变量。它们最初引用的是同一个数组,因此如果您修改数组而不是只为其中一个变量分配一个新数组,它们都会看到变化。

      就个人而言,我认为您在创建此对象时使用了错误的设计模式,这只会使事情变得更加复杂,并且更有可能像您一样制造问题。如果您想维护外部世界无法访问的私有实例变量,该设计模式可能很有用,但如果所有内容都打算公开,它会创建更复杂的定义和维护。

      我的一个编程目标是使用最简单、最简洁的方式来表达所需的功能。

      因此,由于此对象中的所有内容都是公开的,并且可以从对象外部访问,因此这要简单得多,并且不会遇到您刚刚遇到的任何类型的问题:

      function ListManager() {
          this.list = [];
          this.add = function(element) {
             this.list.push(element);
          }
          this.clear = function() {
              this.list = [];
          }    
      }
      

      或者,甚至可以使用原型:

      function ListManager() {
          this.list = [];
      }
      
      ListManager.prototype = {
          add: function(element) {
             this.list.push(element);
          },
          clear: function() {
              this.list = [];
          }
      };
      

      【讨论】:

      • 你说得对,这种设计模式绝对不是声明 public-only-properties 的最佳选择。但发布的代码只是我处理私有属性的真实对象的简化版本。 :-)
      猜你喜欢
      • 1970-01-01
      • 2021-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-22
      • 2018-10-23
      • 2021-08-18
      • 1970-01-01
      相关资源
      最近更新 更多