Можно ли переопределить метод класса JavaScript?
При использовании функции конструктора в JavaScript для создания класса возможно ли позднее переопределить метод класса?
Пример:
function Person(name)
{
this.name = name;
this.sayHello = function() {
alert('Hello, ' + this.name);
};
};
var p = new Person("Bob");
p.sayHello(); // Hello, Bob
Теперь я хотел бы переопределить sayHello
как это:
// This doesn't work (creates a static method)
Person.sayHello() = function() {
alert('Hola, ' + this.name);
};
поэтому, когда я создаю другой Person
, новый sayHello
метод будет вызван:
var p2 = new Person("Sue");
p2.sayHello(); // Hola, Sue
p.sayHello(); // Hello, Bob
РЕДАКТИРОВАТЬ:
Я понимаю, что могу послать аргумент типа "Привет" или "Привет" sayHello
для достижения другого выхода. Я также понимаю, что мог бы просто назначить новую функцию для p2 следующим образом:
p2.sayHello = function() { alert('Hola, ' + this.name); };
Мне просто интересно, могу ли я переопределить метод класса, чтобы новые экземпляры Person
будет использовать новый sayHello
метод.
3 ответа
возможно ли переопределить метод класса позже?
Да. Однако вы не должны назначать новую функцию свойству Person
конструктор, но для самого экземпляра:
var p2 = new Person("Sue");
p2.sayHello(); // Hello, Sue
p2.sayHello = function() {
alert('Hola, ' + this.name);
};
p2.sayHello(); // Hola, Sue
Если вы хотите сделать это для всех новых экземпляров автоматически (и не использовали прототип для метода, который вы легко могли бы обменять, как в ответе @dystroy), вам нужно украсить конструктор:
Person = (function (original) {
function Person() {
original.apply(this, arguments); // apply constructor
this.sayHello = function() { // overwrite method
alert('Hola, ' + this.name);
};
}
Person.prototype = original.prototype; // reset prototype
Person.prototype.constructor = Person; // fix constructor property
return Person;
})(Person);
Чтобы иметь другую функцию для p2, вы можете просто установить sayHello
свойство p2:
p2.sayHello = function(){
alert('another one');
}
p2.sayHello();
Если вы используете прототип, вы также можете изменить его для всех экземпляров Person (и все же вы можете перезаписать его для конкретного человека):
function Person(name)
{
this.name = name;
};
Person.prototype.sayHello = function() {
alert('Hello, ' + this.name);
};
var p = new Person("Bob");
// let's set a specific one for p2
p2.sayHello = function(){
alert('another one');
}
// now let's redefine for all persons (apart p2 which will keep his specific one)
Person.prototype.sayHello = function(){
alert('different!');
}
p.sayHello(); // different!
p2.sayHello(); // another one
Чтобы решить вашу проблему, вы можете использовать объект Reflect
class Person {
public name: string;
constructor(name: string) {
this.name = name;
}
public sayHello(): void {
console.log(`Hello, ${this.name}`)
}
}
const p = new Person("Bob");
p.sayHello(); // Hello, Bob
Reflect.defineProperty(Person.prototype, 'sayHello', { value: function() {
console.log(`Goodbye, ${this.name}`)
}})
p.sayHello(); // Goodbye, Bob