使用构造函数属性重写JavaScript中的方法

使用构造函数属性重写JavaScript中的方法,javascript,Javascript,这是在JavaScript中实现方法重写的一种良好/安全的跨浏览器方式吗 function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; }; Person.prototype.sayHi = function() { return "Hi, my name is " + this.firstName; }; function Employee(firstNa

这是在JavaScript中实现方法重写的一种良好/安全的跨浏览器方式吗

function Person(firstName, lastName)
{
  this.firstName = firstName;
  this.lastName = lastName;
};

Person.prototype.sayHi = function()
{
  return "Hi, my name is " + this.firstName;
};

function Employee(firstName, lastName, position)
{
  Person.call(this, firstName, lastName);
  this.position = position;
};

Employee.prototype = Object.create(Person.prototype);

Employee.prototype.sayHi = function()
{
  return this.constructor.prototype.sayHi() + " I'm a " + this.position;
}
我还可以写:

Employee.prototype.sayHi = function()
{
  return Person.prototype.sayHi() + " I'm a " + this.position;
}
但对于这个解决方案,我指的是直接法,或者

Employee.prototype.sayHi = function()
{
  return this.__proto__.sayHi() + " I'm a " + this.position;
}
但这一次很糟糕,不是交叉划船

编辑:我假设Object.create是交叉浏览器,因为我可以使用垫片

较旧的浏览器不支持,但您可以对其进行填充

我不会用那个。您希望
this.constructor
是继承自的
人,但情况可能并非如此。实际上,最好设置
Employee.prototype.constructor=Employee
,这将导致方法的递归和堆栈溢出

相反,您应该明确引用要使用的函数:

return Person.prototype.sayHi.call(this) + " I'm a " + this.position;
如果您想要动态地使用它,您可以使用

return Object.getPrototypeOf(Employee.prototype).sayHi.call(this) + " I'm a " + this.position;
但请注意,旧浏览器中不支持这一点。因此,如果您需要跨浏览器和干燥方式,请使用模块模式:

(function(proto, super) {
     proto.sayHi = function() {
         return super.sayHi.call(this) + " I'm a " + this.position;
     };
     …
})(Employee.prototype, Person.prototype);
Employee.prototype = (function(super) {
     var proto = Object.create(super);
     proto.sayHi = function() {
         return super.sayHi.call(this) + " I'm a " + this.position;
     };
     …
     return proto;
})(Person.prototype);
或者是原型模式:

(function(proto, super) {
     proto.sayHi = function() {
         return super.sayHi.call(this) + " I'm a " + this.position;
     };
     …
})(Employee.prototype, Person.prototype);
Employee.prototype = (function(super) {
     var proto = Object.create(super);
     proto.sayHi = function() {
         return super.sayHi.call(this) + " I'm a " + this.position;
     };
     …
     return proto;
})(Person.prototype);

您不应该依赖
原型
构造函数
属性来调用父函数,因为通常情况下,该属性应该指向子构造函数

Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
安全地访问父函数还有一些其他方法,比如直接引用
父函数
原型,就像您在第二个示例中尝试做的那样,但是您的方式有问题

如果不使用
call
apply
调用
sayHi
在函数调用期间,此
将指向
Person.prototype
,而这不是您想要的。 您应该通过将上下文对象设置为当前雇员实例来调用
sayHi
,如下所示:

Employee.prototype.sayHi = function() {
  return Person.prototype.sayHi.call(this) + " I'm a " + this.position;
};
另一种方法是在子原型中存储对父原型的引用

 Employee.prototype.super = Person.prototoype;

 Employee.prototype.sayHi = function() {
    return this.super.sayHi.call(this) + " I'm a " + this.position;
 };
我看到的另一个有趣的方法是将子原型的每个函数包装在一个函数中,该函数动态地设置对对象实例上父函数的引用,这样您就只能使用
this.parent()
来调用该函数。但是,我不推荐这种解决方案,因为它会降低性能并增加内存使用


我创建了一个来演示这个概念。

JavaScript中没有“方法重载”这样的东西。我想你在本例中的意思是“覆盖”,但在JS中也没有这样的东西