创建依赖于使用原型的旧构造函数的最佳方法

时间:2013-06-12 23:42:21

标签: javascript constructor clone prototype

所以,假设我有以下构造函数,我的原型我已经修改过:

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;

在我创建了foo之后,我想创建一个新的构造函数bar(),就像一个超级foo类:它具有foo的所有属性,prototpye信息和方法,但它还有一些额外的物业和方法洒在上面。下面的代码是最优雅的方法吗?

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();

运行该代码后,这是我期望得到的

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'

这是“扩展”某些现有构造函数的正确方法,以制作一种“Foo Plus”。基本上,我希望foo继续完全像bar()出现之前那样工作,但是bar要成为一组在foo之上添加的属性和方法。我这样做了吗?

2 个答案:

答案 0 :(得分:1)

好的,我终于完成了我在评论主题中的讨论,以回应问题,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'

答案 1 :(得分:0)

不确定为什么你有这么多代码来拥有原型继承。您可以使用goog.inherit之类的closure library(如果您计划使用闭包编译器进行编译,则使用goog.base)。

以下是一些使用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());