我正在处理一个项目,并决定实现我想要的功能的最佳方式是重写一个方法。当时我没有意识到 javascript 没有调用 super() 的概念,所以我开始做一些研究。
我找到了一篇文章 ( http://blog.salsify.com/engineering/super-methods-in-javascript),它描述了几种调用 super 方法的方法。
虽然我对这些选项中的任何一个都不太满意,但还是想出了以下选项。也可以在 https://jsfiddle.net/fpgm8j9n/ 的 fiddle 上找到.
var Food = function( name ){
this.name = name;
}
Food.prototype.sayName = function(){
console.log( 'I am a ' + this.name );
}
var Fruit = function( name, color ){
Food.call( this, name );
this.color = color;
this.super = Object.getPrototypeOf( Object.getPrototypeOf( this ) );
}
Fruit.prototype = Object.create( Food.prototype );
Fruit.prototype.sayName = function(){
console.log( 'I am a fruit and I am the color ' + this.color );
}
var orange = new Fruit( 'apple', 'red' );
// runs the overridden method in orange
orange.sayName(); // I am a fruit and I am the color red
// runs the super method
orange.super.sayName.call( orange ); // I am a apple
以下是我发布的文章中的第一个示例。只是不必知道您的父原型(prototype),这些本质上是相同的吗?我想出的实现有什么问题或可以改进的地方吗?我对 javascript 中的 OOP 还很陌生,对很多概念感到有点不解。
var Child = Parent.extend({
// ...
doSomething: function(x, y) {
this.doSomethingElse(x);
return Parent.prototype.doSomething.call(this, x, y);
}
});
最佳答案
super
的常见用例是覆盖方法调用它覆盖的方法(从而使用现有功能并使用更多代码进一步扩展它)。所以在你的例子中:
Fruit.prototype.sayName = function(){
this.super.sayName.call(this); // prints "I am a apple"
console.log( 'I am the color ' + this.color ); // prints "I am the color red"
}
var orange = new Fruit( 'apple', 'red' );
orange.sayName();
从对象的方法外部调用对象的父类(super class)方法(如 orange.super.sayName.call(orange);
可以说是非 OO 实践。对象的用户不应该需要知道它的类型或父类(super class)型是什么。他们应该能够要求它做一些事情(比如打印关于它自己的信息)并且对象应该自己弄清楚如何做。
您创建的 super
字段可以很好地用于此目的,因为它允许覆盖方法调用它们覆盖的方法。但是,如果您的继承层次结构超过一层,它就会崩溃:
var Grape = function(variety) {
Fruit.call(this, "grape", "purple");
this.variety = variety;
};
Grape.prototype = Object.create(Fruit.prototype);
Grape.prototype.sayName = function() {
this.super.sayName.call(this);
console.log('I am a ' + this.variety + ' grape');
};
var concordGrape = new Grape("Concord");
concordGrape.sayName(); // unbounded recursion / causes stack overflow
原因是 this.super
字段保持不变,无论层次结构的哪个级别使用它:
this // Grape object
Object.getPrototypeOf(this) // Grape.prototype
Object.getPrototypeOf(Object.getPrototypeOf(this)) // Fruit.prototype
因此,当 Grape.prototype.sayName
调用 this.super.sayName
时,它会按预期调用 Fruit.prototype.sayName
。但是当 Fruit.prototype.sayName
调用 this.super.sayName
时,不幸的是它正在调用自己。
这不能通过在每个级别重新定义 super
来解决:
var Grape = function(variety) {
Fruit.call(this, "grape", "purple");
this.variety = variety;
this.super = Object.getPrototypeOf( Object.getPrototypeOf( this ) );
};
this
指向同一个对象,无论层次结构中的哪个函数引用它。
super
真正需要的是知道正在使用它的函数的层次结构级别(以便它可以从上面的级别调用相应的函数)。除了您链接的文章中的方法外,我不知道有任何万无一失的方法可以做到这一点。
关于javascript - 这种在 javascript 中调用 super() 的方法有什么问题吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29946774/