Метод вызова с использованием прототипа JavaScript
Можно ли вызвать базовый метод из метода прототипа в JavaScript, если он был переопределен?
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
}
};
Ответы
Ответ 1
Я не понял, что именно вы пытаетесь сделать, но обычно выполнение объектно-ориентированного поведения выполняется в следующих строках:
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...*/);
}
Ответ 2
Ну, один способ сделать это - сохранить базовый метод, а затем вызвать его из метода overriden, например
MyClass.prototype._do_base = MyClass.prototype.do;
MyClass.prototype.do = function(){
if (this.name === 'something'){
//do something new
}else{
return this._do_base();
}
};
Ответ 3
Я боюсь, что ваш пример не работает так, как вы думаете. Эта часть:
this.do = function(){ /*do something*/ };
перезаписывает определение
MyClass.prototype.do = function(){ /*do something else*/ };
Поскольку вновь созданный объект уже имеет свойство "делать", он не ищет прототипную цепочку.
Классическая форма наследования в Javascript неудобна и трудно понять. Вместо этого я бы предложил использовать простой шаблон наследования Дугласа Крокфорда. Вот так:
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
По-моему, гораздо более ясный способ обработки объектов, конструкторов и наследования в javascript. Вы можете прочитать больше в Crockfords Javascript: Хорошие части.
Ответ 4
Я знаю, что это сообщение от 4 лет назад, но из-за моего фона С# я искал способ вызвать базовый класс без указания имени класса, а скорее получить его по свойству в подклассе. Поэтому мое единственное изменение в Кристофском ответе было бы
Из этого:
MyClass.prototype.doStuff.call(this /*, args...*/);
Для этого:
this.constructor.prototype.doStuff.call(this /*, args...*/);
Ответ 5
если вы определяете такую функцию (используя ООП)
function Person(){};
Person.prototype.say = function(message){
console.log(message);
}
существует два способа вызова функции прототипа: 1) создать экземпляр и вызвать функцию объекта:
var person = new Person();
person.say('hello!');
а другой способ... 2) вызывает функцию непосредственно из прототипа:
Person.prototype.say('hello there!');
Ответ 6
Альтернатива:
// 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);
}
Ответ 7
Following is the solution that worked for me. It uses Object.getPrototypeOf .
TestA is super that has getName
TestB is a child that overrides getName but, also has
getBothNames that calls the super version of getName as well as the 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());
Ответ 8
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();
};
}
Ответ 9
Если я правильно понимаю, вы хотите, чтобы функциональность базы всегда выполнялась, а часть ее должна быть оставлена для реализаций.
Вам может помочь шаблон дизайна шаблон.
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 */ }
Ответ 10
Если вы знаете свой суперкласс по имени, вы можете сделать что-то вроде этого:
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();
Откроется
called foo in Base
called foo in Sub
called foo in Base
как ожидалось.
Ответ 11
Другой способ с ES5 - явно пересечь цепочку прототипов, используя 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()
Ответ 12
Нет, вам нужно будет предоставить функцию do в конструкторе и функцию do в прототипе разных имен.
Ответ 13
Кроме того, если вы хотите переопределить все экземпляры, а не только один специальный экземпляр, это может помочь.
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();
результат:
doing original
doing override
Ответ 14
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();