Crockford's Prototypical Inheritance - Usage

后端 未结 2 1263
星月不相逢
星月不相逢 2020-12-24 09:02

I\'ve been building a small JS framework for use at my job, and I\'d like to employ Douglas Crockford\'s prototypical inheritance patterns. I think I get the general idea o

相关标签:
2条回答
  • 2020-12-24 09:30

    You got Object.create wrong. The first argument should be an object (maybe that's why people suggested you pass a literal).

    In your first example, you're actually passing undefined:

    Vehicles.Airplane = Object.create(Vehicles.Vehicle()); // the function call will
                                                           // return undefined
    

    The following would work, but it's not very Crockford-ish:

    Vehicles.Airplane = Object.create(new Vehicles.Vehicle());
    

    The way I believe Crockford would do it (or, at least, wouldn't complain of):

    var Vehicles = {};
    
    Vehicles.Vehicle = {
        go : function() {
            // go stuff
        },
        stop : function() {
            // go stuff
        }
    };
    
    Vehicles.Airplane = Object.create(Vehicles.Vehicle, {
        takeOff : { 
            value : function() {
                // take-off stuff
            }
        },
        land : {
            value: function() {
                // land stuff
            }
        }
    });
    

    Note that Vehicles.Vehicle is just a literal, which will be used as the prototype for other objects. When we call Object.create, we pass Vehicles.Vehicle as the prototype, and takeOff and land will be own properties of Vehicles.Airplane. You may then call Object.create again, passing Vehicles.Airplane as the prototype, if you want to create e.g. a Boeing.

    The own properties passed as the second parameter are packed in an object that contains a representation of their property descriptors. The outer keys are the names of your properties/methods, and each one points to another object containing the actual implementation as the value. You may also include other keys like enumerable; if you don't they'll take the default values. You can read more about descriptors on the MDN page about Object.defineProperty.

    0 讨论(0)
  • 2020-12-24 09:38
    Vehicles.Airplane = Object.create(Vehicles.Vehicle());
    

    That line is wrong. You seem to want to use new Vehicles.Vehicle - never call a constructor without new!

    Still, I'm not sure which pattern you want to use. Two are coming to my mind:

    Classical Pattern

    You are using constructor functions just as in standard JS. Inheritance is done by inheriting the prototype objects from each other, and applying the parent constructor on child instances. Your code should then look like this:

    Vehicles.Vehicle = function () {
        // instance-specific properties and methods,
        // initialising
    }
    Vehicles.Vehicle.prototype.go = function () {
         //go forwards
    };
    Vehicles.Vehicle.prototype.stop = function () {
        //stop
    };
    
    Vehicles.Airplane = function() {
        // Vehicles.Vehicle.apply(this, arguments);
        // not needed here as "Vehicle" is empty
    
        // maybe airplane-spefic instance initialisation
    }
    Vehicles.Airplane.prototype = Object.create(Vehicles.Vehicle.prototype, {
        constructor: {value:Vehicles.Airplane, configurable:true}
    }); // inheriting from Vehicle prototype, and overwriting constructor property
    
    Vehicles.Airplane.prototype.takeOff = function () {
       //take off stuff
    };
    
    // usage:
    var airplane = new Vehicles.Airplace(params);
    

    Pure Prototypical Pattern

    You are using plain objects instead of constructor functions - no initialisation. To create instances, and to set up inheritance, only Object.create is used. It is like having only the prototype objects, and empty constructors. instancof does not work here. The code would look like this:

    Vehicles.Vehicle = {
        go: function () {
             //go forwards
        },
        stop: function () {
             //stop
        }
    }; // just an object literal
    
    Vehicles.Airplane = Object.create(Vehicles.Vehicle); // a new object inheriting the go & stop methods
    Vehicles.Airplane.takeOff = function () {
       //take off stuff
    };
    
    // usage:
    var airplane = Object.create(Vehicles.Airplane);
    airplane.prop = params; // maybe also an "init" function, but that seems weird to me
    
    0 讨论(0)
提交回复
热议问题