Best way to create a new constructor that relies on an old one using prototypes

你。 提交于 2019-12-13 04:38:38

问题


So, suppose I have the following constructor function, whose prototype I have modified like so:

function foo(options) {
  this.propA_ = 'whatever';
  this.propB_ = 'something';
  this.propC_ = options.stuff;
  this.randomMethod = function omg() {
    /*code etc etc etc*/
  }
}

foo.prototype.p1 = 1;
foo.prototype.p2 = 2;

After I have made foo, I want to create a new constructor, bar(), that is like a sort super foo: it has all of the properties, prototpye info, and methods of foo, but it ALSO has some extra properties and methods sprinkled on top. Would the following code be the most elegant way to do this?

function foo(options) {
  this.propA_ = 'whatever';
  this.propB_ = 'something';
  this.propC_ = options.stuff;
  this.randomMethod = function omg() {
    /*code etc etc etc*/
  }
}

foo.prototype.p1 = 1;
foo.prototype.p2 = 2;

function bar(options) {
  this = foo(options);
  this.propD_ = 'yet another thing';
  this.propE_ = options.moreStuff;
}

bar.prototype.p3 = 3;
foo.prototype.testing = 'A test';

smallObj = foo()'
bigObj = bar();

After running that code, here is what I would expect to get

console.log(a.p3); //3

bigObj.p2 = 100;
console.log(bigObj.p2); //100
console.log(foo.prototype.p2); //2

console.log(bigObj.randomMethod()); //Will work
console.log(smallObj.p3); //undefined
console.log(smallObj.propA_); //'whatever'
console.log(bigObj.propA_); //'whatever'

foo.prototype.propA_ = 'something totally different'
console.log(bigObj.propA_); //'something totally different'

Is this a correct way of "extending" the functionality of some existing constructor, to make a sort of "Foo Plus". Basically, I'd like for foo to continue to work exactly as it did before bar() came into existence, but for bar to be a set of properties and methods that are added on top of foo. Am I doing this right?


回答1:


Not sure why you have so much code to have prototype inheritance. You can use something like goog.inherit (and goog.base if you plan to use closure compiler to compile) from the closure library.

Here is some sample code that uses goog.inherit:

var goog = {};
/**
 * Inherit the prototype methods from one constructor into another.
 * @param {Function} childCtor Child class.
 * @param {Function} parentCtor Parent class.
 */
goog.inherits = function (childCtor, parentCtor) {
    /** @constructor */
    function tempCtor() { };
    tempCtor.prototype = parentCtor.prototype;
    childCtor.superClass_ = parentCtor.prototype;
    childCtor.prototype = new tempCtor();
    childCtor.prototype.constructor = childCtor;
};
/** @constructor */
var GrandParent = function (arg1) {
    window['console'].log("grandparent constructor called with arg1:", arg1);
}
GrandParent.prototype.doSomething = function () {
    return "From GrandParent";
}
/** @constructor */
var Parent = function (arg1, arg2) {
    GrandParent.call(this, arg1);
    window['console'].log("parent constructor called with arg1:", arg1);
    window['console'].log("parent constructor called with arg2:", arg2);
}
goog.inherits(Parent, GrandParent);
/** @override */
Parent.prototype.doSomething = function () {
    return Parent.superClass_.doSomething() + " From Parent";
}
/** @constructor 
* @extends Parent */
var Child = function (arg1, arg2, arg3) {
    Parent.call(this, arg1, arg2);
    window['console'].log("child constructor called with arg1:", arg1);
    window['console'].log("child constructor called with arg2:", arg2);
    window['console'].log("child constructor called with arg3:", arg3);
}
goog.inherits(Child, Parent);
/** @override */
Child.prototype.doSomething = function () {
    return Child.superClass_.doSomething() + " From Child";
}

var c = new Child("arg1", "arg2", "arg3");
console.log(c.doSomething());



回答2:


Ok, I finally worked through the discussion I have in the comment thread in response to the quesion, and this is the answer I came up with. I'll repost the code here - thank you to everyone who helped me work through this!

function foo(options) {
    this.propA_ = 'whatever';
    this.propB_ = 'something';
    this.propC_ = options.stuff;
    this.randomMethod = function omg() {
        /*code etc etc etc*/
    };
}
foo.prototype.p1 = 1;
foo.prototype.p2 = 2;

function bar(options) {
    //this = new foo(options);
    var parent = new foo(options);
    this.prototype = parent.prototype;

    for (var x in parent) {
        if (parent.hasOwnProperty(x)) {
            console.log('iterating past'+x);
            this[x] = parent[x];
        }
    }

    this.propD_ = 'yet another thing';
    this.propE_ = options.moreStuff;
}
// Make `bar` inherit from an instance of `foo`
bar.prototype = Object.create(foo.prototype);

// Add properties to the bar prototype
bar.prototype.p3 = 3;

// Not sure what you were doing here
//foo.prototype.testing = 'A test';

var myOpts = {
    stuff: 'a cat',
    moreStuff: 'many dogs'
};

var smallObj = new foo(myOpts);
var bigObj = new bar(myOpts);


console.log(smallObj.p2); //2

console.log(bigObj.p2); //2
bigObj.p2 = 100;
console.log(bigObj.p2); //100
console.log(foo.prototype.p2); //2

//console.log(bigObj.randomMethod()); //Will work
console.log(smallObj.p3); //undefined
console.log(smallObj.propA_); //'whatever'
console.log(bigObj.propA_); //'whatever'

foo.prototype.propA_ = 'something totally different';
console.log(bigObj.propA_); //'whatever'


来源:https://stackoverflow.com/questions/17077167/best-way-to-create-a-new-constructor-that-relies-on-an-old-one-using-prototypes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!