JavaScript:函数是否应该能够使用 Object.create() 创建自身的实例
JavaScript: Should a function be able to create instances of itself with Object.create()
我的用例如下:我想创建一个生产各种数据传输对象 (DTO) 的工厂。它们必须易于序列化,并且必须有一些额外的方法。
我当前的实现如下所示 (simplified):
window.Dto = function(type, properties)
{
var
self = this,
values = {},
object = Object.create(self);
properties.forEach(function(prop){
Object.defineProperty(object, prop, {
get: function() { return values[prop]; },
set: function(value) { values[prop] = value; },
enumerable: true
});
});
this.getType = function()
{
return type;
};
this.doSomeMagic = function()
{
// ...
};
return object;
};
// creating a DTO of the Transport.Motorized.Car class
var carObject = new Dto("Transport.Motorized.Car", ["vendor", "model", "color", "vmax", "price"]);
(注意:我不想为这些对象中的每一个创建一个明确的 class,因为它们有很多,并且它们是从服务器端导出的。另外,你看到的 properties
上面的参数,实际上是一个带有验证约束等的元数据映射)
我使用创建了 50,000 个此类对象的循环进行了快速性能检查。 performance.now()
告诉我它花了超过 1 秒的时间——看起来不错,但不是太令人印象深刻。
我的问题主要是:工厂从它自己的原型创建一个实例(如果我理解正确的话)和 returns 它可以吗?它有什么副作用?有没有更好的方法?
据我了解工厂函数,它们的重点是不需要创建函数本身的新实例。相反,它只是 returns 一个新创建的对象。
因此,我不使用新创建的实例(通过 new
运算符)的实例属性(通过 this
),而是创建一个对象(我们称它为 factoryProto
) 并将所有 "instance" 方法分配给该对象。
然后,您可以使用 factoryProto
作为新 object
的 [[Prototype]]
:
window.Dto = function(type, properties) {
var factoryProto = {
getType: function() {
return type;
},
doSomeMagic: function() {
// ...
}
},
values = {},
object = Object.create(factoryProto);
properties.forEach(function(prop) {
Object.defineProperty(object, prop, {
get: function() { return values[prop]; },
set: function(value) { values[prop] = value; },
enumerable: true
});
});
return object;
};
// creating a DTO of the Transport.Motorized.Car class
var carObject = Dto("Transport.Motorized.Car", ["vendor", "model", "color", "vmax", "price"]);
如果你想充分利用原型链,你可以在工厂函数之外定义 factoryProto
。要跟踪 type
,您可以将其添加为不可枚举的 object
属性:
window.Dto = (function() {
var factoryProto = {
getType: function() {
return this.type;
},
doSomeMagic: function() {
// ...
}
};
return function(type, properties) {
var values = {},
object = Object.create(factoryProto);
properties.forEach(function(prop) {
Object.defineProperty(object, prop, {
get: function() { return values[prop]; },
set: function(value) { values[prop] = value; },
enumerable: true
});
});
Object.defineProperty(object, 'type', {
value: type,
enumerable: false
});
return object;
};
})();
// creating a DTO of the Transport.Motorized.Car class
var carObject = Dto("Transport.Motorized.Car", ["vendor", "model", "color", "vmax", "price"]);
我的用例如下:我想创建一个生产各种数据传输对象 (DTO) 的工厂。它们必须易于序列化,并且必须有一些额外的方法。
我当前的实现如下所示 (simplified):
window.Dto = function(type, properties)
{
var
self = this,
values = {},
object = Object.create(self);
properties.forEach(function(prop){
Object.defineProperty(object, prop, {
get: function() { return values[prop]; },
set: function(value) { values[prop] = value; },
enumerable: true
});
});
this.getType = function()
{
return type;
};
this.doSomeMagic = function()
{
// ...
};
return object;
};
// creating a DTO of the Transport.Motorized.Car class
var carObject = new Dto("Transport.Motorized.Car", ["vendor", "model", "color", "vmax", "price"]);
(注意:我不想为这些对象中的每一个创建一个明确的 class,因为它们有很多,并且它们是从服务器端导出的。另外,你看到的 properties
上面的参数,实际上是一个带有验证约束等的元数据映射)
我使用创建了 50,000 个此类对象的循环进行了快速性能检查。 performance.now()
告诉我它花了超过 1 秒的时间——看起来不错,但不是太令人印象深刻。
我的问题主要是:工厂从它自己的原型创建一个实例(如果我理解正确的话)和 returns 它可以吗?它有什么副作用?有没有更好的方法?
据我了解工厂函数,它们的重点是不需要创建函数本身的新实例。相反,它只是 returns 一个新创建的对象。
因此,我不使用新创建的实例(通过 new
运算符)的实例属性(通过 this
),而是创建一个对象(我们称它为 factoryProto
) 并将所有 "instance" 方法分配给该对象。
然后,您可以使用 factoryProto
作为新 object
的 [[Prototype]]
:
window.Dto = function(type, properties) {
var factoryProto = {
getType: function() {
return type;
},
doSomeMagic: function() {
// ...
}
},
values = {},
object = Object.create(factoryProto);
properties.forEach(function(prop) {
Object.defineProperty(object, prop, {
get: function() { return values[prop]; },
set: function(value) { values[prop] = value; },
enumerable: true
});
});
return object;
};
// creating a DTO of the Transport.Motorized.Car class
var carObject = Dto("Transport.Motorized.Car", ["vendor", "model", "color", "vmax", "price"]);
如果你想充分利用原型链,你可以在工厂函数之外定义 factoryProto
。要跟踪 type
,您可以将其添加为不可枚举的 object
属性:
window.Dto = (function() {
var factoryProto = {
getType: function() {
return this.type;
},
doSomeMagic: function() {
// ...
}
};
return function(type, properties) {
var values = {},
object = Object.create(factoryProto);
properties.forEach(function(prop) {
Object.defineProperty(object, prop, {
get: function() { return values[prop]; },
set: function(value) { values[prop] = value; },
enumerable: true
});
});
Object.defineProperty(object, 'type', {
value: type,
enumerable: false
});
return object;
};
})();
// creating a DTO of the Transport.Motorized.Car class
var carObject = Dto("Transport.Motorized.Car", ["vendor", "model", "color", "vmax", "price"]);