Javascript functional inheritance with prototypes

后端 未结 4 1713
心在旅途
心在旅途 2021-02-01 08:58

In Douglas Crockford\'s JavaScript: The Good Parts he recommends that we use functional inheritance. Here\'s an example:

var mammal = function(spec, my         


        
4条回答
  •  梦如初夏
    2021-02-01 09:29

    To proper use Javascript-prototype based inheritance you could use fastClass https://github.com/dotnetwise/Javascript-FastClass

    You have the simpler inheritWith flavor:

      var Mammal = function (spec) {
        this.spec = spec;
    }.define({
        clearThroat: function () { return "Ahem" },
        getName: function () {
            return this.spec.name;
        },
        says: function () {
            return this.clearThroat() + ' ' + spec.saying || '';
        }
    });
    
    var Cat = Mammal.inheritWith(function (base, baseCtor) {
        return {
            constructor: function(spec) { 
                spec = spec || {};
                baseCtor.call(this, spec); 
            },
            purr: function() {
                return this.clearThroat() + " purr";
            },
            getName: function() {
                return this.says() + ' ' + this.spec.name + this.says();
            }
        }
    });
    
    var kitty = new Cat({ name: "Fluffy" });
    kitty.purr(); // Ahem purr
    kitty.getName(); // Ahem Fluffy Ahem
    

    And if you are very concerned about performance then you have the fastClass flavor:

    var Mammal = function (spec) {
        this.spec = spec;
    }.define({
        clearThroat: function () { return "Ahem" },
        getName: function () {
            return this.spec.name;
        },
        says: function () {
            return this.clearThroat() + ' ' + spec.saying || '';
        }
    });
    
    var Cat = Mammal.fastClass(function (base, baseCtor) {
        return function() {
            this.constructor = function(spec) { 
                spec = spec || {};
                baseCtor.call(this, spec); 
            };
            this.purr = function() {
                return this.clearThroat() + " purr";
            },
            this.getName = function() {
                return this.says() + ' ' + this.spec.name + this.says();
            }
        }
    });
    
    var kitty = new Cat({ name: "Fluffy" });
    kitty.purr(); // Ahem purr
    kitty.getName(); // Ahem Fluffy Ahem
    

    Btw, your initial code doesn't make any sense but I have respected it literally.

    fastClass utility:

    Function.prototype.fastClass = function (creator) {
        var baseClass = this, ctor = (creator || function () { this.constructor = function () { baseClass.apply(this, arguments); } })(this.prototype, this)
    
        var derrivedProrotype = new ctor();
    
        if (!derrivedProrotype.hasOwnProperty("constructor"))
            derrivedProrotype.constructor = function () { baseClass.apply(this, arguments); }
    
        derrivedProrotype.constructor.prototype = derrivedProrotype;
        return derrivedProrotype.constructor;
    };
    

    inheritWith utility:

    Function.prototype.inheritWith = function (creator, makeConstructorNotEnumerable) {
        var baseCtor = this;
        var creatorResult = creator.call(this, this.prototype, this) || {};
        var Derrived = creatorResult.constructor ||
        function defaultCtor() {
            baseCtor.apply(this, arguments);
        }; 
        var derrivedPrototype;
        function __() { };
        __.prototype = this.prototype;
        Derrived.prototype = derrivedPrototype = new __;
    
        for (var p in creatorResult)
            derrivedPrototype[p] = creatorResult[p];
    
        if (makeConstructorNotEnumerable && canDefineNonEnumerableProperty) //this is not default as it carries over some performance overhead
            Object.defineProperty(derrivedPrototype, 'constructor', {
                enumerable: false,
                value: Derrived
            });
    
        return Derrived;
    };
    

    define utility:

    Function.prototype.define = function (prototype) {
        var extendeePrototype = this.prototype;
        if (prototype)
            for (var p in prototype)
                extendeePrototype[p] = prototype[p];
        return this;
    }
    

    [* Disclaimer, I am the author of the open source package and the names of the methods themselves might be renamed in future` *]

提交回复
热议问题