对象文字内的工厂模式,以实现迭代和反射

时间:2015-10-31 11:28:23

标签: javascript

我希望能够从工厂构造实例并使它们看起来像void BST::find_sum(node * root1,node * root2,int sum) { if(root1==NULL) return; if(root2==NULL) { return; } if((root1->data+root2->data)==sum) { if(root1==root2) return; cout<<"\t "<<root1->data<<" + "<<root2->data<<" = "<<sum; return; } find_sum(root1,root2->left,sum); find_sum(root1,root2->right,sum); return; 创建的实例 - 意味着构造函数和原型与new Instance()创建的实例无法区分。 / p>

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

new

请注意,“classname”“Instance”不会传递给通用创建者。

另一个要求是此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等语言内的一种语言

JSBin

1 个答案:

答案 0 :(得分:0)

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

如果您稍后创建name等于_name的{​​{1}}函数,可以在此处移除该类的名称,只需按ctor <{1}} 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

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

classic instanceof Classic
instance instanceof App.factory.Instance

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

以下是我提出的符合您要求的代码。

&#13;
&#13;
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);
&#13;
&#13;
&#13;