簡単に言えば、関数のプロトタイプにメソッドを定義するということは、この関数のすべてのインスタンスからプロトタイプ チェーンの 1 つ上のリンクになるオブジェクトにメソッドを定義したことを意味します。
その関数のすべてのインスタンスの共通の「親」または「上にあるオブジェクト」と考えることができます。
したがって、メソッドを使用するには、プラグインをインスタンス化し、関数を呼び出す必要があります。
function Pikaday() {}
Pikaday.prototype = {
showYearPicker: function() {
console.log('called');
}
}
let pikaday = new Pikaday();
pikaday.showYearPicker(); // <-- call the function on the prototype
これが行うことは、定義されているかどうかを確認することですpikaday
。showYearPicker
定義されていないため、proto チェーンを上って、そのオブジェクトがそれを持っているかどうかを確認します。
つまり、これは基本的に JS エンジンが舞台裏で行っていることです。
let pikaday = new Pikaday();
pikaday.__proto__.showYearPicker();
ここでのprotoはデモンストレーション用であり、レガシー目的で ES6 で最近標準化されたばかりですが、この動作は JS エンジンに任せる必要があります (仕様では、この proto リンクを呼び出します[[Prototype]]
)。
必要に応じて、プロトタイプにアクセスする適切な方法は、Object.getPrototypeOfを使用することです(+ES6 では、意味的により明確なReflect.getPrototypeOfを使用できます) 。
function Pikaday() {}
console.log(
Object.getPrototypeOf(new Pikaday()) === Pikaday.prototype
);
console.log(
Reflect.getPrototypeOf(new Pikaday()) === Pikaday.prototype
);
コードの問題の 1 つは、getElementsByClassNameがこのクラスを持つノードのNodeList (配列ではない)を返すことです。
つまり、このリストをループして、各要素にハンドラーをアタッチする必要があります。
let nodes = document.getElementsByClassName('pika-year-label');
Array.from(nodes) // convert NodeList to an array so we can use forEach
.forEach(node => {
// attach a handler on each node
node.onclick = function (){
console.log("asfd");
}
});
// Side Note: You can also use array spread to convert the node list to an array
// [...nodes].forEach( ... )
または、すべての要素の共通の親にハンドラーをアタッチして、動作を委任します。
document.body.onclick = function(e) {
if (e.target.classList.contains('pika-year-label')) {
console.log("asfd");
}
}
最後に、この関数を既存の関数のプロトタイプに追加するだけの場合は、そのプロトタイプのメソッドとして単純に定義する方法があります。
function Pikaday() {}
// define a method on the existing prototype
Pikaday.prototype.showYearPicker = function() {
console.log('called');
};
let pikaday = new Pikaday();
pikaday.showYearPicker(); // <-- call the function on the prototype