3

obj.prototype.__proto__ = events.EventEmitter.prototype

上記のコードを時々見たことがありますが、Google で調べたところ、この行ですべての EventEmitter プロパティが obj にコピーされているとのことです。また、次のようなコードも表示されます。

obj.__proto__ = events.EventEmitter.prototype

だから私はそれらが同じかどうか疑問に思っていますか?


この記事で最初の使用法を見ました。この記事では、著者が例を挙げています。

var events = require('events');
function Door(colour) {
  this.colour = colour;
  events.EventEmitter.call(this);
  this.open = function()
  {
    this.emit('open');
  }
}
Door.prototype.__proto__ = events.EventEmitter.prototype;
var frontDoor = new Door('brown');
  frontDoor.on('open', function() {
  console.log('ring ring ring');
});

frontDoor.open();

そして彼は次のように説明します。

この行:Door.prototype.__proto__ = events.EventEmitter.prototype;すべての EventEmitter プロパティを Door オブジェクトにコピーします。

2番目の方法については、 hexoのソースで見たinit.js に、次のコードがあります。

    var hexo = global.hexo = {
    get base_dir(){return baseDir},
    get public_dir(){return baseDir + 'public/'},
    get source_dir(){return baseDir + 'source/'},
    get theme_dir(){return baseDir + 'themes/' + config.theme + '/'},
    get plugin_dir(){return baseDir + 'node_modules/'},
    get script_dir(){return baseDir + 'scripts/'},
    get scaffold_dir(){return baseDir + 'scaffolds/'},
    get core_dir(){return path.dirname(dirname) + '/'},
    get lib_dir(){return dirname + '/'},
    get version(){return version},
    get env(){return env},
    get safe(){return safe},
    get debug(){return debug},
    get config(){return config},
    get extend(){return extend},
    get render(){return render},
    get util(){return util},
    get call(){return call},
    get i18n(){return i18n.i18n},
    get route(){return route},
    get db(){return db}
  };

  hexo.cache = {};

  // Inherits EventEmitter
  hexo.__proto__ = EventEmitter.prototype;

  // Emit "exit" event when process about to exit
  process.on('exit', function(){
    hexo.emit('exit');
  });
4

3 に答える 3

3

ステートメントは同じではありません。

プロパティは通常、関数でのみ使用でき、特別なプロパティはありませんobj.prototype.__proto__ = events.EventEmitter.prototype。通常の (関数ではない) オブジェクトのプロパティとして定義されている場合の意味。Constructor.prototype.__proto__ = events.EventEmitter.prototypeConstructorprototype

言い換えれば、obj与えられたコードの最初の行では、意味をなすために (コンストラクター) 関数である必要があり、関数が のような一般的な変数名を持つことは非常にまれobjです。

正確な最初のステートメントを見つけたソースを共有すると、問題が解決する可能性があります。


2 番目の例は最も単純です。コンストラクターは関与しません。hexoオブジェクトリテラルで作成されたプレーンなオブジェクトです。作成者は、 EventEmitter メソッドをメソッドを通じて使用できるようにしたいので、プロパティhexoに割り当てます。これにより、実際に のプロトタイプが変更されます。EventEmitter.prototype__proto__hexo

最初のコード例は、やや複雑です。ここで作成者は、Door関数によって構築されたすべてのオブジェクトが EventEmitter メソッドへのアクセスを提供することを保証したいと考えています。Door 関数によって構築されたオブジェクトはDoor.prototype、そのプロトタイプとして取得されます。この特定のプロトタイプには、そのプロトタイプとして EventEmitter が含まれているため、EventEmitter 関数には、プロトタイプ チェーンを 2 ステップ上に移動することでアクセスできます。

「すべての EventEmitter プロパティを Door オブジェクトにコピーします。」- この特定のコメントは誤解を招きます。プロパティはコピーされません。起こるのはこれだけです。

door = new Door
door.on("open", function() { console.log("door has opened")})

のプロトタイプdoorは現在Door.prototypeです。アクセスしようとしたときにプロパティ (この場合onは ) が見つからない場合、JS エンジンはこのプロトタイプを調べます。door--のプロトタイプも定義されDoor.prototypeていないonため、JS エンジンはDoor.prototypeプロトタイプがあるかどうかを確認します。の形で行いevents.EventEmitter.prototypeます。そして、このオブジェクトにはonプロパティが定義されています。

これにより、物事がやや明確になることを願っています。Javascript のプロトタイプの継承は非常にトリッキーです。

something.prototype.__proto__ の設定に関する混乱も参照してください。

于 2013-08-07T13:06:09.360 に答える
2

プロパティは通常、prototypeコンストラクター、つまり新しいオブジェクトを作成する関数にあります。コンストラクターのprototypeは、新しくインスタンス化されたオブジェクトのプロトタイプとして使用されるオブジェクトです。

オブジェクトの__proto__プロパティは、オブジェクトが最初にインスタンス化されたときにプロトタイプとして使用されたオブジェクトを指します。これは非標準であるため、JavaScript エンジンがサポートするという保証はありません。

Door.prototypeあなたの例では、それらがおよびを参照していることがわかりますhexo.__proto__。ここでの決定的な違いは、それがDoorコンストラクターであるのに対しhexo、オブジェクトのインスタンスであることです。

ただし、Door.prototypeはオブジェクトのインスタンスであるため、そのプロトタイプを取得するには、 を使用する必要があります__proto__

どちらの場合も、代入の RHS はコンストラクターであるため、 を参照してprototypeください。

要約すると、コンストラクターによって使用されるプロトタイプが必要な場合は、 を使用しますprototype。インスタンス化されたオブジェクトのプロトタイプが必要な場合は、__proto__.

実際には、 を使用した方がよい場合がありますObject.getPrototypeOf

ソース

于 2013-08-07T12:53:05.600 に答える