組み込みのMapオブジェクトを拡張しようとしています。これは動作します一部です:ネイティブオブジェクトを拡張するファクトリ/クラス
var Attributes = class extends Map {
get text() {
let out = [];
for (let [ k, v ] of this.entries()) {
out.push(k + '="' + v + '"');
}
return out.join(' ');
}
// simplified for brevity!
set text (raw) {
this.clear();
var m, r = /(\w+)="([^"]+)"/g;
while ((m = r.exec(raw))) {
this.set(m[1], m[2]);
}
}
};
var a = new Attributes();
a.text = 'id="first"';
console.log(a.get('id')); // first
a.set('id', 'second');
console.log(a.text); // id="second"
しかし、私は自分のライブラリにシームレスにこのクラスを統合し、むしろ、コンストラクタとして、二重の目的を果たすファクトリメソッドを公開します。ユーザーは、この特定の方法が珍しいことを知る必要はありません。それは物事を複雑にするだけです。私自身のコードでは、入力検証の目的でinstanceofを使用できる必要があります。これは私がつもりです:
var obj = {};
obj.attr = function (text) {
if (new.target) {
this.text = text;
} else {
return new obj.attr(text);
}
};
console.log(obj.attr() instanceof obj.attr); // true
は、あまりにも、上記の動作します。しかし、どのように2つのアプローチを組み合わせようとも、ChromeとFirefoxの両方でさまざまなエラーが発生します。例えば以下のコード。例外TypeError "this.entries(...)[Symbol.iterator]機能ではありません" 例外:
var obj = {};
obj.attr = function (text) {
if (new.target) {
this.text = text;
} else {
return new obj.attr(text);
}
};
obj.attr.prototype = Object.assign(new Map(), {
get text() {
let out = [];
for (let [ k, v ] of this.entries()) {
out.push(k + '="' + v + '"');
}
return out.join(' ');
},
// simplified for brevity!
set text (raw) {
this.clear();
var m, r = /(\w+)="([^"]+)"/g;
while ((m = r.exec(raw))) {
this.set(m[1], m[2]);
}
}
});
は、私がここにおよび/または誤解何をしないのですか?
更新:はObject.setPrototypeOf()
を使用しても可能ですが、パフォーマンスの低下はおそらく相当になります。 でもを使用してが可能です。正確にはこれがObject.setPrototypeOf()
とどのように違うのかはわかりません。リフレクションは現在のブラウザでは最適化されていないため、一般的に遅いようです。
var Attributes = class extends Map {
constructor (text) {
super();
this.text = text;
}
get text() {
let out = [];
for (let [ k, v ] of this.entries()) {
out.push(k + '="' + v + '"');
}
return out.join(' ');
}
// simplified for brevity!
set text (raw) {
this.clear();
if (!raw) return;
var m, r = /(\w+)="([^"]+)"/g;
while ((m = r.exec(raw))) {
this.set(m[1], m[2]);
}
}
};
var obj = {};
obj.attr = function (text) {
if (new.target) {
return Reflect.construct(Attributes, [ text ], obj.attr);
} else {
return new obj.attr(text);
}
};
obj.attr.prototype = Object.create(Attributes.prototype);
console.log(obj.attr() instanceof obj.attr);
console.log(obj.attr() instanceof Attributes);
console.log(obj.attr() instanceof Map);
var a = obj.attr();
a.text = 'id="first"';
console.log(a.get('id'));
a.set('id', 'second');
console.log(a.text);
申し訳ありませんが、次のことができるようにしたいので、 '新しい属性(...)と'属性(...)の両方を使用しますか? –
はい。まあ、一種。ドキュメントでは、 'obj.attr()'を使用するようにユーザーに指示します。私は、 'new obj.attr()'も同様に機能することを省略する予定です。 –
this.entriesはエラーをスローしますが、this.entriesメソッドのコードは含めないと書いています。 – Sebastian