Est-il possible d'appeler la méthode de base à partir d'une méthode prototype en JavaScript si elle a été remplacée?
MyClass = function(name){
this.name = name;
this.do = function() {
//do somthing
}
};
MyClass.prototype.do = function() {
if (this.name === 'something') {
//do something new
} else {
//CALL BASE METHOD
}
};
Je ne comprenais pas exactement ce que vous tentiez de faire, mais normalement, le comportement spécifique à un objet est appliqué comme suit:
function MyClass(name) {
this.name = name;
}
MyClass.prototype.doStuff = function() {
// generic behaviour
}
var myObj = new MyClass('foo');
var myObjSpecial = new MyClass('bar');
myObjSpecial.doStuff = function() {
// do specialised stuff
// how to call the generic implementation:
MyClass.prototype.doStuff.call(this /*, args...*/);
}
Une façon de le faire serait de sauvegarder la méthode de base, puis de l'appeler à partir de la méthode surchargée, comme
MyClass.prototype._do_base = MyClass.prototype.do;
MyClass.prototype.do = function(){
if (this.name === 'something'){
//do something new
}else{
return this._do_base();
}
};
Je crains que votre exemple ne fonctionne pas comme vous le pensez. Cette partie:
this.do = function(){ /*do something*/ };
écrase la définition de
MyClass.prototype.do = function(){ /*do something else*/ };
Puisque l'objet nouvellement créé a déjà une propriété "do", il ne recherche pas la chaîne de prototypes.
La forme classique de l'héritage en Javascript est difficile à comprendre. Je suggérerais d'utiliser plutôt le modèle de succession simple de Douglas Crockford. Comme ça:
function my_class(name) {
return {
name: name,
do: function () { /* do something */ }
};
}
function my_child(name) {
var me = my_class(name);
var base_do = me.do;
me.do = function () {
if (this.name === 'something'){
//do something new
} else {
base_do.call(me);
}
}
return me;
}
var o = my_child("something");
o.do(); // does something new
var u = my_child("something else");
u.do(); // uses base function
À mon avis, une méthode beaucoup plus claire de gestion des objets, des constructeurs et de l'héritage en javascript. Vous pouvez lire plus dans Crockfords Javascript: Les bonnes parties .
Je sais que cet article date d'il y a 4 ans, mais à cause de mon arrière-plan C #, je cherchais un moyen d'appeler la classe de base sans avoir à spécifier le nom de la classe, mais plutôt à l'obtenir par une propriété de la sous-classe. Donc, mon seul changement à réponse de Christoph serait
À partir de ceci:
MyClass.prototype.doStuff.call(this /*, args...*/);
Pour ça:
this.constructor.prototype.doStuff.call(this /*, args...*/);
si vous définissez une fonction comme celle-ci (en utilisant la POO)
function Person(){};
Person.prototype.say = function(message){
console.log(message);
}
il existe deux manières d'appeler une fonction prototype: 1) créer une instance et appeler la fonction objet:
var person = new Person();
person.say('hello!');
et l’autre voie est ... 2) appelle la fonction directement à partir du prototype:
Person.prototype.say('hello there!');
Cette solution utilise Object.getPrototypeOf
TestA
est super qui a getName
TestB
est un enfant qui remplace getName
mais a également getBothNames
qui appelle la version super
de getName
ainsi que le child
version
function TestA() {
this.count = 1;
}
TestA.prototype.constructor = TestA;
TestA.prototype.getName = function ta_gn() {
this.count = 2;
return ' TestA.prototype.getName is called **';
};
function TestB() {
this.idx = 30;
this.count = 10;
}
TestB.prototype = new TestA();
TestB.prototype.constructor = TestB;
TestB.prototype.getName = function tb_gn() {
return ' TestB.prototype.getName is called ** ';
};
TestB.prototype.getBothNames = function tb_gbn() {
return Object.getPrototypeOf(TestB.prototype).getName.call(this) + this.getName() + ' this object is : ' + JSON.stringify(this);
};
var tb = new TestB();
console.log(tb.getBothNames());
Une alternative :
// shape
var shape = function(type){
this.type = type;
}
shape.prototype.display = function(){
console.log(this.type);
}
// circle
var circle = new shape('circle');
// override
circle.display = function(a,b){
// call implementation of the super class
this.__proto__.display.apply(this,arguments);
}
function NewClass() {
var self = this;
BaseClass.call(self); // Set base class
var baseModify = self.modify; // Get base function
self.modify = function () {
// Override code here
baseModify();
};
}
Si je comprends bien, vous voulez que la fonctionnalité de base soit toujours exécutée, tandis qu’une partie de celle-ci devrait être laissée aux implémentations.
Vous pourriez être aidé par le modèle de conception ' méthode du modèle '.
Base = function() {}
Base.prototype.do = function() {
// .. prologue code
this.impldo();
// epilogue code
}
// note: no impldo implementation for Base!
derived = new Base();
derived.impldo = function() { /* do derived things here safely */ }
Une autre méthode avec ES5 consiste à parcourir explicitement la chaîne de prototypes à l’aide de Object.getPrototypeOf(this)
const speaker = {
speak: () => console.log('the speaker has spoken')
}
const announcingSpeaker = Object.create(speaker, {
speak: {
value: function() {
console.log('Attention please!')
Object.getPrototypeOf(this).speak()
}
}
})
announcingSpeaker.speak()
Si vous connaissez votre classe par son nom, vous pouvez faire quelque chose comme ceci:
function Base() {
}
Base.prototype.foo = function() {
console.log('called foo in Base');
}
function Sub() {
}
Sub.prototype = new Base();
Sub.prototype.foo = function() {
console.log('called foo in Sub');
Base.prototype.foo.call(this);
}
var base = new Base();
base.foo();
var sub = new Sub();
sub.foo();
Cela va imprimer
called foo in Base
called foo in Sub
called foo in Base
comme prévu.
De plus, si vous voulez remplacer toutes les instances et pas seulement une instance spéciale, celle-ci pourrait vous aider.
function MyClass() {}
MyClass.prototype.myMethod = function() {
alert( "doing original");
};
MyClass.prototype.myMethod_original = MyClass.prototype.myMethod;
MyClass.prototype.myMethod = function() {
MyClass.prototype.myMethod_original.call( this );
alert( "doing override");
};
myObj = new MyClass();
myObj.myMethod();
résultat:
doing original
doing override
Non, vous devrez donner la fonction do dans le constructeur et la fonction do dans les noms différents du prototype.