我试图扩展内置的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
以上,也起作用。但是,无论我如何结合这两种方法,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()
但性能损失可能会很大。它的也可能使用Reflect.construct()
。对我来说这并不明显,但这与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