【问题标题】:Problem with prototypal inheritance and instance array [duplicate]原型继承和实例数组的问题[重复]
【发布时间】:2011-03-22 05:08:57
【问题描述】:

我使用原型继承并希望拥有带有实例数组的对象。因此,如果我从一个具有实例数组的对象派生一些对象并访问该数组,那么它们都共享该数组。我想将一些东西推送到数组中,并且只在实际对象中更改数组,而不是在所有其他对象中。

使用标准原型继承和 Object.create 来解决这个问题的优雅方法是什么?

var sys = require('sys');

var obj ={
    data: [],
    add: function(what){
        this.data.push(what)
    }
};

var one = Object.create(obj);
one.add(1);

var other = Object.create(obj);
other.add(2);

sys.puts(other.data.length); // is 2, but should be 1

【问题讨论】:

    标签: javascript inheritance prototype node.js


    【解决方案1】:
    var ObjectName = function(){
        this.data = [];
    }
    
    ObjectName.prototype.add = function(what){
        this.data.push(what);
    };
    
    var one = new ObjectName();
    one.add(1);
    

    【讨论】:

    • 我想在 Object.create 中使用原型继承
    • 您仍然可以使用 object.create。但是您必须运行构造函数来使用实例变量 this.data 初始化对象。 var one = Object.create(ObjectName.prototype); ObjectName.call(one); one.add(1);
    【解决方案2】:

    Object.create 没有优雅的解决方案,因为你做错了。

    你想要的是:

    function MyArray() {
        this.data = [];  // per-instance data here
    }
    
    MyArray.prototype = {
        add: function(what) {  // prototype methods here
            this.data.push(what);
        }
    };
    
    var one = new MyArray;
    one.add(1);
    ...
    

    【讨论】:

      【解决方案3】:

      你也可以替换:

      add: function(what) {  // prototype methods here
          this.data.push(what);
      }
      

      add: function(what) {  // prototype methods here
          this.data = this.data.concat(what);
      }
      

      因为这将创建一个新变量,而不是将其推入原型实例中。

      【讨论】:

        【解决方案4】:

        Object.create 可以通过传递带有属性描述符的第二个参数向新对象添加属性。

        var sys = require('sys');
        
        var obj = {
            add: function(what){
                this.data.push(what)
            }
        };
        
        var one = Object.create(obj, {
            data: {
                value: [],
                writable: true,
                enumerable: true,
                configurable: true
            }
        });
        one.add(1);
        
        var other = Object.create(obj, {
            data: {
                value: [],
                writable: true,
                enumerable: true,
                configurable: true
            }
        });
        other.add(2);
        
        sys.puts(other.data.length); // should be 1
        

        当然,您可能希望将其放入构建器函数中,这样您就不会重复自己:

        function makeThing() {
            return Object.create(obj, {
                data: {
                    value: [],
                    writable: true,
                    enumerable: true,
                    configurable: true
                }
            });
        }
        

        虽然,此时你基本上是在编写一个构造函数(优点是你不需要用 new 调用它)。此外,如果您将writableenumerableconfigurable 设置为true,您可以按正常方式设置属性,通过实现一个简单版本的Object.create:

        function makeThing() {
            var newObj = Object.create(obj);
            newObj.data = [];
            return newObj;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-12-28
          • 2015-09-29
          • 1970-01-01
          • 1970-01-01
          • 2011-04-10
          • 1970-01-01
          • 2019-01-24
          • 2016-07-04
          相关资源
          最近更新 更多