Javascript prototypes and instance creation

前端 未结 2 1125
生来不讨喜
生来不讨喜 2020-12-14 11:17

I apologize because this topic comes up a lot, but I have not been able to have this adequately explained in anything I\'ve read today.

I am trying to make a simple

相关标签:
2条回答
  • 2020-12-14 11:39

    Consider a classroom full of students. Putting something on the prototype is like putting something on the white board for them all to see. When you're declaring

    Collection.prototype._innerList = [];
    

    you're giving every collection that property; regardless of calling new Collection() any changes to the white board affects all students. However, if you define it within the constructor, or one of the functions as this.variableName = [], each copy will have its own variableName, like handing each student a handout. Obviously, there's some cases when it's okay to have something on the white board, such as instructions that will be universal from student to student, but if each item is going to be different for each student, it should be an individual property. Hope this explanation makes sense...

    You want to be doing this.

    function Collection() {
        if (!this instanceof Collection)
            return new Collection();
        this._innerList = [];
        this._xref = {};
    
        return this;
    }
    
    Collection.prototype.count = function() {
        return this._innerList.length;
    };
    Collection.prototype.add = function(obj) {
        this._xref[obj.name] = this._innerList.push(obj) - 1;
    }
    Collection.prototype.get = function(id) {
        if (typeof id == "string") {
            return this._innerList[this._xref[id]];
        } else {
            return this._innerList[id];
        }
    };
    
    var foo = new Collection();
    foo.add({name: "someitem", value:"hello world"});   
    console.log(foo.count()); // 1
    
    var bar= new Collection();
    bar.add({name: "someotheritem", value:"hello world"});
    console.log(bar.count()); // 1
    

    http://jsfiddle.net/vXbLL/

    Edit

    Not really relevant to your question, but it's something I do so I will throw it out there. Whenever I'm doing something on the prototype, if I'm not returning something, I return this. It allows chaining, so you could do instance.function1().function2().function3() as long as function1 and function2 return this.

    0 讨论(0)
  • 2020-12-14 11:48

    You can think of a prototype as giving all objects of that class shared variables. Like static variables in a c++ class if that makes any sense. That's ok to do for functions because they're all the same for each instance of the class. However, if you want the object to have its own non-shared variable, you shouldn't use the prototype. One simple way to do it is to assign them in the constructor method like this:

    function Collection() 
    {
    this._innerList = [];
    this._xref = {};
    }
    
    Collection.prototype.count = function () { return this._innerList.length; };
    Collection.prototype.add = function (obj) {
        this._xref[obj.name] = this._innerList.push(obj) - 1;
    }
    Collection.prototype.get = function (id) {
        if (typeof id == "string") {
            return this._innerList[this._xref[id]];
        } else {
            return this._innerList[id];
        }
    };
    
    var foo = new Collection();
    foo.add({name: "someitem", value:"hello world"});   // foo.count()== 1
    document.write(foo.count(),"<br>");
    
    var bar= new Collection();
    bar.add({name: "someotheritem", value:"hello world"}); // bar.cou
    document.write(bar.count(),"<br>");
    
    0 讨论(0)
提交回复
热议问题