Javascript 使用原型创建依赖于旧构造函数的新构造函数的最佳方法
假设我有以下构造函数,我对其原型进行了如下修改:Javascript 使用原型创建依赖于旧构造函数的新构造函数的最佳方法,javascript,constructor,clone,prototype,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
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之上的属性和方法。我这样做对了吗?好的,我终于完成了我在评论帖子中针对这个问题的讨论,这就是我得出的答案。我将在这里重新发布代码-感谢所有帮助我完成这项工作的人
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'
不知道为什么有这么多代码要进行原型继承。您可以从中使用类似(和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());
对吗?不,跑吧。这将失败<代码>此=foo(选项)似乎你只是在猜测。网上有很多关于遗产的信息供你学习。是的,我知道我的理解很差。我在这里研究了好几条线索,但我仍然不太清楚到底发生了什么。我试图为我自己的例子辩护。是的,我知道它失败了,我的问题是为什么。好吧,所以我对你的小提琴做了一些修改:我可以把我的脑袋绕到为什么
this=newfoo(opts)
是错误的:这是指由bar()构造的对象,显然我不能随意地重新定义该对象;我可以设置它的属性,可以添加方法等等,但我不能只是重新定义它。我想做的是让bar()中的“this”继承foo的原型……好吧,我几乎就拥有了它。链接到最新的小提琴:所以基本上原型是复制过来的,所以我想我是对的。此外,foo原型的变化也反映在bar原型中,这也是非常棒的。我的问题是在foo()本身中构造的属性没有被传输到bar()。我小提琴中的第45行没有产生它应该产生的结果。为什么会这样?如何在构造函数中设置属性以转移到继承它的新对象?最好使用prototype声明方法属性,因为它们不会因每个实例而改变,但会改变值属性,您可以使用this.something=“my instance value”
来声明这些属性。关于prototype和这个
行为的示例代码的简单解释如下:您可以在chrome中按F12,在控制台中运行代码并使用它来更好地理解它。