Using Object.assign and Object.create for inheritance

前端 未结 3 1871
面向向阳花
面向向阳花 2020-12-12 18:29

I typically implement inheritance along the following lines.

function Animal () { this.x = 0; this.y = 0;}

Animal.prototype.locate = function() { 
  console         


        
3条回答
  •  忘掉有多难
    2020-12-12 18:56

    Yes, it is that simple. In your example with Object.create/Object.assign, you are using a factory function to create new instances of duck (similar to the way jQuery creates new instances if you select an element with var body = $('body')). An advantage of this code style is, that it doesn't force you to call a constructor of animal when you want to create a new duck instance (as opposed to ES2015 Classes).

    Differences in initialization

    Maybe one interesting tidbit that works slightly differently than if you were to use a constructor (or any other initialization function):

    When you create a duck instace, all the properties of animal are in the [[Prototype]] slot of the duck instance.

    var daffy = duck();
    console.log(daffy); // Object { speak: function() }
    

    So daffy does not have any own x and y properties yet. However, when you call the following, they will be added:

    daffy.move(6, 7);
    console.log(daffy); // Object { speak: function(), x: 6, y: 7 }
    

    Why? In the function-body of animal.move, we have the following statement:

    this.x = this.x + x; 
    

    So when you call this with daffy.move, this refers to daffy. So it will try to assign this.x + x to this.x. Since this.x is not yet defined, the [[Prototype]] chain of daffy is traversed down to animal, where animal.x is defined.

    Thus in the first call, the this.x on the right side of the assignment refers to animal.x, because daffy.x is not defined. The second time daffy.move(1,2) is called, this.x on the right side will be daffy.x.

    Alternative Syntax

    Alternatively, you could also use Object.setPrototypeOf instead of Object.create/Object.assign (OLOO Style):

    var duck = function () {
       var duckObject = {
           speak : function () { 
               console.log("quack");
               return this;
           }
       };
       return Object.setPrototypeOf(duckObject, animal);
    }
    

    Naming Conventions

    I'm not aware of any established conventions. Kyle Simpson uses uppercase letters in OLOO, Eric Elliot seems to use lowercase. Personally I would stick with lower-case, because the object literals that act as constructors are already fully fledged objects themselves (not just blueprint, like classes would be).

    Singleton

    If you only wanted a single instance (e.g. for a singleton), you could just call it directly:

    var duck = Object.assign(Object.create(animal), {
        speak : function () { 
            console.log("quack");
            return this;
        }
    });
    
    duck.move(6, 7).locate().speak();
    

提交回复
热议问题