4

JavaScript でプロトタイプの継承がどのように機能するか把握したと思ったとき、それまで考えもしなかった問題に突き当たりました。

次の単純な JavaScript コードを見てください。

var Observable = function () {
  this.events = [];
};

Observable.prototype.addEvent = function (e) {
  this.events.push(e);
};

var Model = function () {};
Model.prototype = new Observable();

var appModel = new Model();
var taskModel = new Model();

appModel.addEvent('Hello');
taskModel.addEvent('World');

または のいずれappModel.eventsかを見るtaskModel.eventsと、同じ配列が得られます: ['Hello', 'World']。私がやろうとしているのは、新しいものごとに、できるだけきれいな方法でModel独自の配列を持たせることです。events作品の次の実装Model

var Model = function () {
  this.events = [];
};
Model.prototype = new Observable();

ただし、より多くのプロパティが追加されると、Observableこれはより扱いにくくなります。これを次のように修正できると思いました。

var Model = function () {
  this.prototype.constructor.apply(this, arguments);
};
Model.prototype = new Observable();

JavaScript の経験が豊富な方は、これがエラーをスローすることに気付いていると思います: TypeError: Cannot read property 'constructor' of undefined.

Model要約すると、私は各 newがプロパティを継承しObservable、それぞれModelが独自の を持つ方法を探していeventsます。これは非常にクラスに似ていると思いますが、JavaScript のプロトタイプ ベースの継承のみを使用してこれを行う方法を知りたいです。

Dean Edward の Base.js を見たことは注目に値します。以下の作品:

var Observable = Base.extend({
  constructor: function () {
    this.events = [];
  },
  addEvent: function (e) {
    this.events.push(e);
  }
});

var Model = Observable.extend({
  constructor: function () {
    this.base();
  }
});

var appModel = new Model();
var taskModel = new Model();

appModel.addEvent('Hello');
taskModel.addEvent('World');

しかし、以下はそうではありません:

var Observable = Base.extend({
  events: [],
  addEvent: function (e) {
    this.events.push(e);
  }
});

var Model = Observable.extend({
  constructor: function () {
    this.base();
  }
});

var appModel = new Model();
var taskModel = new Model();

appModel.addEvent('Hello');
taskModel.addEvent('World');

要点に加えて、クラス ライブラリを使用せずに JavaScript プロトタイプでこれを行う方法を学びたいと思います。

4

3 に答える 3

0

私は自分の問題を解決するためにこれを試しました:

var Model = function () {
  this.prototype.constructor.apply(this, arguments);
};
Model.prototype = new Observable();

実際の解決策はこれを行うことです:

var Model = function () {
  Model.prototype.constructor.apply(this, arguments);
};
Model.prototype = new Observable();

これにより、それぞれModelに独自のevents配列が与えられるだけでなく、コンストラクターが作成Modelする他のプロパティもそれぞれ与えられます。Observableここでの小さなオーバーヘッドModel.prototype.eventsは、アクセスされない空の配列です。

于 2012-12-29T23:18:03.543 に答える
0

コードの最初のビットが の各インスタンスにModel共通のevents配列を持たせる理由は、それらが の単一の共通インスタンスへのプロトタイプ参照を持っているためですObservable。つまり、こうすることで

Model.prototype = new Observable();

基本的に、JavaScript に「 のすべてのインスタンスを、この特定のインスタンスModelように動作させる」ように指示しています。Observable

JavaScript でプロトタイプの継承を正しく実行するには、いくつかの方法があります。最近標準化された ECMAScript 6 を使用できる場合は、まさにこの目的のために設計された便利な newclassおよびキーワードを使用できます。extends

class Observable {
    constructor() {
        this.events = [];
    }

    addEvent() {
        this.events.push(e);
    }
}

class Model extends Observable {
    // Model definition
};

残念ながら、ECMAScript 6 のサポートはまだ十分ではありません。ECMAScript 5 はObject.createを追加しました。

var Observable = function () {
    this.events = [];
};

Observable.prototype.addEvent = function (e) {
    this.events.push(e);
};

var Model = function () {
    Observable.call(this);
};
Model.prototype = Object.create(Observable.prototype);

MDN には、この手法を使用した JavaScript の OOP に関する非常に優れた記事があります。

于 2016-01-21T23:10:54.013 に答える
0

ここで私が理解したことは、各インスタンスに個別のイベント配列を持たせたいということです。そうであれば、答えに従ってください:

function Model(){
  this.events = [];
  this.addEvent = function(eventName){
    this.events.push(eventName);
  };
  this.getEvents = function(){
    return this.events;
  }
}

var m1 = new Model;
var m2 = new Model;
m1.addEvent("eve-1");
m2.addEvent("eve-2");
m1.getEvents(); //["eve-1"]
m2.getEvents(); //["eve-2"]

あなたの場合、イベントをインスタンスではprototypeなく直接追加しているため、すべてのインスタンスに追加されます...これが役立つことを願っています

于 2012-12-29T22:28:56.260 に答える