Javascript 对象文字内部的工厂模式,以实现可编辑性和反射性
我希望能够从工厂构造实例,并使它们看起来像由Javascript 对象文字内部的工厂模式,以实现可编辑性和反射性,javascript,Javascript,我希望能够从工厂构造实例,并使它们看起来像由new Instance()创建的实例——这意味着构造函数和原型与由new创建的实例无法区分 工厂将驻留在一个对象文本中,因此它的调用看起来像 var instance=App.factory.Instance.create(arg1,...); 请注意,“classname”的“Instance”并没有传递给泛型创建者 另一个要求是该实例的成员驻留在对象文本中,如果没有提供构造函数,则使用默认值(无操作) 驻留在文本中的成员是为了迭代和反射的目的,
new Instance()
创建的实例——这意味着构造函数和原型与由new
创建的实例无法区分
工厂将驻留在一个对象文本中,因此它的调用看起来像
var instance=App.factory.Instance.create(arg1,...);
请注意,“classname”的“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);
我让它工作了一半,但我感到困惑,并在基本方法上寻求改进。此外,我是否缺少任何可以使实例
与经典构造对象区分开来的连线
拓宽这一思路,似乎应该有一个库,它将采用这种模板并生成工厂,其中类通过对象.defineProperty
构造,从而提供更多的控制-即\u readonly
等。一种语言中的一种语言
如果您稍后创建一个函数,其名称
等于\u name
,该函数只调用ctor
,就像这样调用ctor.call(this)代码>
看起来,为了对实例不可知,您添加了\u name
约定。您还可以创建一个函数,该函数接受应用程序
对象,并递归添加\u name
字段。另一种可能是将工厂
而不是实例
传递给将要添加创建
方法的函数
that._ctor.name=that._name;
此代码不执行任何操作,因为函数的名称是只读属性。它也不需要,因为代码eval('(函数'+that.\u name+'(){})
已经用您想要的名称创建了函数
fn.prototype.constructor=fn
当您声明一个函数时,它会自动获取一个原型,并将构造函数字段设置为该函数。您必须使用rv.constructor.prototype.constructor=that设置原型的构造函数字段代码>因为您用模板替换了原型。您可以在rv=new that.之前或之后执行此操作代码>
这就是让工厂创建的对象与正常创建的对象区别开来的原因。为了使instanceof
操作符工作App.factory.Instance
需要是构造函数
下面是我根据您的要求编写的代码
App={
工厂:{
实例:{
模板:{
c:3,
d:4
},
_静态:{
e:5,
f:6
},
构造函数:函数(a,b){
这个a=a;
这个.b=b;
}
}
}
};
函数初始化(工厂){
for(工厂中的变量名称){
var构造函数=eval('(函数'+name+'(){}');
constructor.prototype=factory[name]。模板;
Object.defineProperty(constructor.prototype,'constructor'{
值:构造函数,
可枚举:false
});
for(工厂中的var属性[名称]。\u静态){
构造函数[属性]=工厂[名称]。_静态[属性];
}
var previous=工厂[name]。构造函数;
var create=函数(){
var实例=新构造函数();
如果(先前){
previous.apply(实例、参数);
}
返回实例;
}
工厂[名称]=建造商;
工厂[名称]。创建=创建;
}
}
初始(应用程序工厂);
经典函数(a,b){
这个a=a;
这个.b=b;
};
Classic.prototype.c=3;
Classic.prototype.d=4;
经典。e=5;
经典。f=6;
var classic=新classic(1,2);
var instance=App.factory.instance.create(1,2);
console.log('classic',classic);
log('instance',instance);
log('classic.constructor',classic.constructor);
log('instance.constructor',instance.constructor);
log('instance.constructor.name',instance.constructor.name);
log('classic.constructor.name',classic.constructor.name);
log('classic instanceof classic',classic instanceof classic);
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);
log('instance.a',instance.a);
log('instance.b',instance.b);
log('instance.c',instance.c);
log('instance.d',instance.d);
log('App.factory.Instance.e',App.factory.Instance.e');
log('App.factory.Instance.f',App.factory.Instance.f')代码>如果没有找到任何库执行此操作,请将其作为一个标志。
that._ctor.name=that._name;
fn.prototype.constructor=fn
classic instanceof Classic
instance instanceof App.factory.Instance