onload
がHTMLElement.prototype
で定義されたアクセサープロパティであるため、このエラーが発生します。
アクセサーをHTML要素でのみ呼び出すことになっていますが、HTML要素ではないHTMLImageElement.prototype
でセッターを呼び出しています。
この機能を定義する場合は、代わりにdefineProperty
を使用してください。
Object.defineProperty(HTMLImageElement.prototype, 'onload', {
configurable: true,
enumerable: true,
value: function() {
console.log(this, "loaded");
}
});
var img = new Image();
img.onload();
警告:組み込みのプロトタイプをいじり悪い習慣です。
ただし、これは関数を定義するだけです。この関数の名前がonload
であっても、イメージがロードされたときに関数が魔法のように呼び出されることはありません。
でも、リスナーでさえ内部的なものだからです。そうではありません。画像がロードされると、ブラウザはonload
メソッドを呼び出します。代わりに、onload
メソッドを設定すると、その関数はイベントリスナーとして内部的に格納され、画像がロードされるとブラウザはload
イベントリスナーを実行します。代わりに、適切な方法は、カスタム要素を作成するために、Webコンポーネントを使用することでしょう
:
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function() {
var img = document.createElement('img');
img.src = this.getAttribute('src');
img.addEventListener('load', function() {
console.log('loaded');
});
this.appendChild(img);
};
document.registerElement('my-img', {prototype: proto});
<my-img src="/favicon.ico"></my-img>
多くのブラウザのサポートはしかし、まだありません。
いいえ組み込みプロトタイプを使用しないでください。 – Bergi
http://www.ncyoung.com/?p=194 – mplungjan
@Bergiこれは空のビルトインプロトタイプです。これはイベントリスナーであり、カスタム関数のカスタム境界のために作られています。 –