是否可以重新定义 JavaScript 类的方法?

IT技术 javascript class
2021-01-31 22:00:01

在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

编辑:

我意识到我可以发送像“Hello”或“Hola”这样的参数sayHello来完成不同的输出。我也意识到我可以像这样简单地为 p2 分配一个新函数:

p2.sayHello = function() { alert('Hola, ' + this.name); };

我只是想知道是否可以重新定义类的方法,以便 的新实例Person将使用新sayHello方法。

2个回答

以后可以重新定义类的方法吗?

是的。但是,您不能将新函数分配给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);
@mikerodent 上述方法不适用于 ES6 classes。它是一个比较复杂那里。
2021-03-13 22:00:01
@Bergi:我不确定我是否理解。一个普通的函数可以分配给一个对象属性,并将作为一个方法(即将获得'this')。箭头函数将充当函数而不是方法(不会得到“this”)
2021-03-13 22:00:01
@PumWalters 当然,箭头函数不是构造函数
2021-03-14 22:00:01
我尝试了你的“装饰构造函数”的想法。它目前似乎不起作用,并且出现“需要新的”错误。我不是 JS 专家,但这可能与较新版本的 JS 有关(我想我目前正在使用 ES6(async/await)...还是 ES7 ???)。
2021-03-17 22:00:01
请注意,这仅适用于正确的功能,不适用于箭头功能
2021-03-22 22:00:01

要为 p2 设置不同的功能,您只需设置sayHellop2属性:

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
我知道原型并且我可以为 p2 分配一个新函数,但我想要的是直接更改 Person 以便 Person 的新实例将使用“Hola”函数。抱歉,我没有说得更清楚。
2021-03-18 22:00:01