问题
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