In Javascript, the difference between 'Object.create' and 'new'

后端 未结 2 504
眼角桃花
眼角桃花 2021-02-03 14:25

I think the difference has clicked in my head, but I\'d just like to be sure.

On the Douglas Crockford page Prototypal Inheritance in JavaScript, he says

2条回答
  •  爱一瞬间的悲伤
    2021-02-03 15:07

    Your assumptions are correct, but there is another pattern that Douglas doesn't talk much about - the prototype can be used for properties as well. Your person class could have been written as:

    var Person = function(name, age) {
        this.name = name;
        this.age = age;
    }
    Person.prototype.name = null; //default value if you don't init in ctor
    Person.prototype.age = null;
    Person.prototype.gender = "male";
    Person.prototype.toString = function(){return this.name + ', ' + this.age;};
    

    In this case, iterating over properties of an instance of this class, as you do in your example, would generate no output for the 'gender' property.

    EDIT 1: The assignment of name and age in the constructor do make the properties visible by hasOwnProperty (thanks @matt for reminding me of this). The unassigned gender property would not be visible until someone sets it on the instance.

    EDIT 2: To further add to this, I present an alternative inheritance pattern - one that I have personally used for very large projects:

    var inherits = function(childCtor, parentCtor) {
      function tempCtor() {};
      tempCtor.prototype = parentCtor.prototype;
      childCtor.superclass = parentCtor.prototype; 
      childCtor.prototype = new tempCtor();
      childCtor.prototype.constructor = childCtor;
    };
    
    var Person = function(name){
        this.name = name;
    }
    Person.prototype.name = "";
    Person.prototype.toString = function(){
        return "My name is " + this.name;
    }
    
    var OldPerson = function(name, age){
        OldPerson.superclass.constructor.call(this);
        this.age = age
    };
    inherits(OldPerson, Person);
    OldPerson.prototype.age = 0;
    OldPerson.prototype.toString = function(){
        var oldString =  OldPerson.superclass.toString.call(this);
        return oldString + " and my age is " + this.age;
    }
    

    This is a fairly common pattern with a small twist - the parent class is attached to the child via the "superclass" property permitting you to access methods/properties overridden by the child. Technically, you could replace OldPerson.superclass with Person, however that is not ideal. If you ever changed OldPerson to inherit from a class other than Person, you would have to update all references to Person as well.

    EDIT 3: Just to bring this full circle, here is a version of the "inherits" function which takes advantage of Object.create and functions exactly the same as I previously described:

    var inherits = function(childCtor, parentCtor) {
        childCtor.prototype = Object.create(parentCtor.prototype);
        childCtor.superclass = parentCtor.prototype; 
    };
    

提交回复
热议问题