gpt4 book ai didi

javascript - 对象字面量中的工厂模式以实现可迭代性和反射

转载 作者:行者123 更新时间:2023-12-03 11:27:08 25 4
gpt4 key购买 nike

我希望能够从工厂构造实例并让它们看起来像 new Instance() 创建的实例-- 意味着构造函数和原型(prototype)与 new 创建的实例没有区别.

工厂将驻留在对象字面量中,因此它的调用看起来像

var instance=App.factory.Instance.create(arg1,...);

请注意,“类名”“实例”不会传递给通用创建者。

另一个要求是这个 Instance 的成员驻留在对象字面量中,如果未提供构造函数,则使用默认值(无操作)。

驻留在文字中的成员用于迭代和反射,这就是为什么任何在空白处执行操作的方法都行不通的原因。

/* jshint laxcomma: true */
window.App={
_name:'App'// convention
,factory:{
_name:'factory'
// begin specifying classes
,Instance:{ // this is a mini-factory of type 'Instance',
// a 'create' method is dynamically injected when 'factory' is initialized
_name:'Instance'
,ctor:function Instance(a,b){ // OPTIONAL specified constructor, want to ditch fn name here if possible
}
,template:{ // Instance spec container. Is like 'Instance.prototype'
//_name:'template' // convention, but will not be a member of 'instance'
valueMember:'something' // this will exist on finished 'prototype'
,funcMember:function(){ // this will exist on finished 'prototype'
}
}
,_static:{ // these will be placed on 'Instance' (constructor)
_name:'_static' // convention, but not placed
,valueMember:'something' // this will exist on 'Instance' (constructor)
,funcMember:function(){ // this will exist on 'Instance' (constructor)
}
}
//,create:function(){} is injected during init of factory
}// - Instance
// more classes like Instance here...
}
};
App.factory.Instance.create=function(){ // this must be generic/agnostic to 'Instance'
var that=this; // this is 'Instance:'
function init(){
if (that.ctor===undefined) { // user did not provide constructor
//that.ctor=new Function(''); // BAD WAY
// make a generic constructor with correct name
that.ctor=eval('(function '+that._name+'(){})');
}
// preserve constructor for reuse
that._ctor=that.ctor;
delete that.ctor;
var i;
if (typeof that._static==='object') { // put statics on constructor
for (i in that._static) {
if (i!=='_name') { // ignore convention
that._ctor[i]=that._static[i];
}
}
}
// doing it whole here, should be a cleaned-of-convention duplicate object
that._ctor.prototype=that.template;
that._ctor.name=that._name;
// this line confuses me, something should be done, do I need it?
//that._ctor.prototype.constructor=that._ctor; // produces 'constructor' in instance
}
// look in cache
if (that._ctor===undefined) {
init();
}
// NOW THE HARD PART - HOW TO INVOKE
var rv;
var fn=that._ctor;
//rv=construct(fn,arguments);
//rv= new fn();
rv=new that._ctor();
// HERE
// fn.prototype.constructor=fn;
// My problem at this point is getting instance.constructor to
// not be 'Object' but if I include the line above
// it shows 'constructor' as iterable
// however THIS LINE WORKS, but why? BUT Why do I have to do it here, after construction?
rv.constructor.prototype.constructor=that._ctor;
// NO that._ctor.prototype.constructor=that._ctor; puts 'constructor' on instance
return rv;
}; //-create
function Classic(a,b){

}
Classic.prototype.member="member";
var classic=new Classic();

var instance=App.factory.Instance.create();
console.log('classic',classic);
console.log('instance',instance);
console.log('classic.constructor',classic.constructor);
console.log('instance.constructor',instance.constructor);
console.log('instance.constructor.name',instance.constructor.name);
console.log('classic.constructor.name',classic.constructor.name);

我的工作进行了一半,但我感到困惑,并寻求改进基本方法。另外,我是否遗漏了任何会使 instance 的接线?与经典构造的对象有区别吗?

扩展这个想法,似乎应该有一个库可以采用这种模板并生产通过 Object.defineProperty 构建类的工厂。从而给予更多的控制权——即_readonly等等。语言中的语言。

JSBin

最佳答案

,ctor:function Instance(a,b){ // OPTIONAL specified constructor, want to ditch fn name here if possible

如果您稍后创建一个 name 等于 _name 的函数,它可以像这样调用 ctor,则可以在此处删除类的名称ctor.call(this);

App.factory.Instance.create=function(){ // this must be generic/agnostic to 'Instance'

看起来,为了与 Instance 无关,您添加了 _name 约定。您还可以创建一个函数来获取您的 App 对象并递归地添加 _name 字段。另一种可能性是将 factory 而不是 Instance 传递给要添加 create 方法的函数。

that._ctor.name=that._name;

此代码不执行任何操作,因为函数名称是只读属性。它也不是必需的,因为代码 eval('(function '+that._name+'(){})') 已经创建了您想要的名称的函数。

fn.prototype.constructor=fn

当您声明一个函数时,它会自动获得一个原型(prototype),其中构造函数字段设置为该函数。您必须使用 rv.constructor.prototype.constructor=that._ctor; 设置原型(prototype)的构造函数字段,因为您用模板替换了原型(prototype)。您可以在 rv=new that._ctor(); 之前或之后完成此操作。

classic instanceof Classic
instance instanceof App.factory.Instance

这将使您的工厂创建的对象与正常创建的对象区分开来。为了使 instanceof 运算符起作用,App.factory.Instance 需要是构造函数。

这是我根据您的要求编写的代码。

App = {
factory: {
Instance: {
template: {
c: 3,
d: 4
},
_static: {
e: 5,
f: 6
},
constructor: function (a, b) {
this.a = a;
this.b = b;
}
}
}
};

function init(factory) {
for (var name in factory) {
var constructor = eval('(function ' + name + '(){})');
constructor.prototype = factory[name].template;
Object.defineProperty(constructor.prototype, 'constructor', {
value: constructor,
enumerable: false
});
for (var property in factory[name]._static) {
constructor[property] = factory[name]._static[property];
}
var previous = factory[name].constructor;
var create = function () {
var instance = new constructor();
if (previous) {
previous.apply(instance, arguments);
}
return instance;
}
factory[name] = constructor;
factory[name].create = create;
}
}

init(App.factory);

function Classic(a, b) {
this.a = a;
this.b = b;
};
Classic.prototype.c = 3;
Classic.prototype.d = 4;
Classic.e = 5;
Classic.f = 6;

var classic = new Classic(1, 2);
var instance = App.factory.Instance.create(1, 2);

console.log('classic', classic);
console.log('instance', instance);
console.log('classic.constructor', classic.constructor);
console.log('instance.constructor', instance.constructor);
console.log('instance.constructor.name', instance.constructor.name);
console.log('classic.constructor.name', classic.constructor.name);
console.log('classic instanceof Classic', classic instanceof Classic);
console.log('instance instanceof App.factory.Instance', instance instanceof App.factory.Instance);

console.log('classic.a', classic.a);
console.log('classic.b', classic.b);
console.log('classic.c', classic.c);
console.log('classic.d', classic.d);
console.log('Classic.e', Classic.e);
console.log('Classic.f', Classic.f);

console.log('instance.a', instance.a);
console.log('instance.b', instance.b);
console.log('instance.c', instance.c);
console.log('instance.d', instance.d);
console.log('App.factory.Instance.e', App.factory.Instance.e);
console.log('App.factory.Instance.f', App.factory.Instance.f);

关于javascript - 对象字面量中的工厂模式以实现可迭代性和反射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33451026/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com