1

これは、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はクロスブラウザーであると想定しました

4

2 に答える 2

1

いいえ。

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

Object.create古いブラウザではサポートされていませんが、shim できます。

Employee.prototype.sayHi = function() {
    return this.constructor.prototype.sayHi() + " I'm a " + this.position;
}

私はそれを使用しません。継承元であることを期待this.constructorしますPersonが、そうではない場合があります。実際には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;

Object.getPrototypeOfただし、古いブラウザではサポートされていないことに注意してください。したがって、クロスブラウザーで DRY の方法が必要な場合は、モジュール パターンを使用します。

(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);
于 2013-04-19T13:34:09.517 に答える
1

通常、そのプロパティは子コンストラクターを指す必要があるため、親関数を呼び出すために のconstructorプロパティに依存しないでください。prototype

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

parent2番目の例でやろうとしているようにプロトタイプを直接参照するなど、親関数に安全にアクセスする方法は他にもいくつかありますが、その方法には何か問題があります。

またはsayHiを使用せずに呼び出すと、関数呼び出し中にが指されますが、それはあなたが望むものではありません。次のように、コンテキスト オブジェクトを現在の従業員インスタンスに設定して呼び出す必要があります。callapplythisPerson.prototypesayHi

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;
 };

私が見たもう 1 つの興味深いアプローチは、子プロトタイプのすべての関数を、オブジェクト インスタンスの親関数への参照を動的に設定する関数でラップすることです。これthis.parent()により、関数の呼び出しにのみ使用できます。ただし、パフォーマンスが低下し、メモリ使用量が増加するため、このソリューションはお勧めしません。

その概念を示すためにjsFiddleを作成しました。

于 2013-04-19T13:35:27.743 に答える