如何根据类名和参数创建对象

开发时遇到这样的需求,希望通过一个类似factory的机制来创建对象,这个机制接收两个参数,一个是对象所属的类,另一个是参数数组,例如:

 

这里cls是一个类(即javascript函数),args是一个参数数组,例如[arg1, arg2, ....],希望这个函数返回的对象等同于下面代码的效果:

 

容易想到,我们应该用apply方法,因为javascript中构建对象的过程就是执行构造函数的过程。而构造函数与普通函数性质完全一样,只是它会被new关键字自动调用而已。apply方法接收2个对象,第一个是函数运行的上下文对象,即this对象。在这里对象尚未构建,因此我们使用一个空对象:

 

 

为验证可行性,我们创建1个类:

 

下面用getObject创建一个employee对象并确认其属性:

 

可以看到,正如我们所希望的,对象被正确创建。

 

但事情到此并没有完。问题出在apply函数的第一个参数上:我们用了一个空对象。实际上起始对象不一定为空。当empoyee的prototype也被定义时,就不为空了,例如,我们通过prototype为employee增加一个方法:

 

 

再创建对象,并调用show方法:

 

会出错,说show方法不存在,其原因就是我们只用到了emp的构造函数,却没用到其prototype。

 

实际上,根据javascript规范,new一个对象时,首先是以函数的prototype对象作为原型,在这个基础上去调用创建新对象。因此我们需要修改getObject方法,让apply以prototype为基础。

 

但同时,不能直接以employee.prototype作为apply的第一个参数,因为那是直接修改了empoyee的原型。我们需要创建一份prototype的拷贝。如果用过dojo.delegate方法,我们应该知道复制对象最高效的做法,用其思路,来重写getObject方法:

 

 

 

 

可以看到,show方法也被正确构建。这说明得到了正确的getObject方法。完整的例子可参见:

http://jsfiddle.net/V94Z2/

 

虽然这个需求的实现看似简单,实际上它要求熟知javascript new关键字的工作原理,知其原理,我们就能成功的把对象的构建分成2个部分,一部分是prototype的复制,另一部分是构造函数的执行。用自己的代码去实现这两部分,就能实现我们需要的功能了。

 

 

 

 

 

posted on 2010-08-18 11:10  springside5  阅读(404)  评论(0编辑  收藏  举报