javascript prototype

原型真谛

正当我们感概万分时,天空中一道红光闪过,祥云中出现了观音菩萨。只见她手持玉净瓶,轻拂翠柳枝,洒下几滴甘露,顿时让JavaScript又添新的灵气。

观音洒下的甘露在JavaScript的世界里凝结成块,成为了一种称为“语法甘露”的东西。这种语法甘露可以让我们编写的代码看起来更象对象语言。

要想知道这“语法甘露”为何物,就请君侧耳细听。

在理解这些语法甘露之前,我们需要重新再回顾一下JavaScript构造对象的过程。

我们已经知道,用 var anObject = new aFunction() 形式创建对象的过程实际上可以分为三步:第一步是建立一个新对象;第二步将该对象内置的原型对象设置为构造函数prototype引用的那个原型对象;第 三步就是将该对象作为this参数调用构造函数,完成成员设置等初始化工作。对象建立之后,对象上的任何访问和操作都只与对象自身及其原型链上的那串对象 有关,与构造函数再扯不上关系了。换句话说,构造函数只是在创建对象时起到介绍原型对象和初始化对象两个作用。

那么,我们能否自己定义一个对象来当作原型,并在这个原型上描述类,然后将这个原型设置给新创建的对象,将其当作对象的类呢?我们又能否将这个原型中的一个方法当作构造函数,去初始化新建的对象呢?例如,我们定义这样一个原型对象:

var  Person  =   // 定义一个对象来作为原型类
{
Create:  function (name, age)  // 这个当构造函数
{
this .name  =  name;
this .age  =  age;
},
SayHello:  function ()  // 定义方法
{
alert( “ Hello, I’m  “   +   this .name);
},
HowOld:  function ()  // 定义方法
{
alert( this .name  +   “  is  “   +   this .age  +   “  years old. “ );
}
};

这个JSON形式的写法多么象一个C#的类啊!既有构造函数,又有各种方法。如果可以用某种形式来创建对象,并将对象的内置的原型设置为上面这个“类”对象,不就相当于创建该类的对象了吗?

但遗憾的是,我们几乎不能访问到对象内置的原型属性!尽管有些浏览器可以访问到对象的内置原型,但这样做的话就只能限定了用户必须使用那种浏览器。这也几乎不可行。

那么,我们可不可以通过一个函数对象来做媒介,利用该函数对象的prototype属性来中转这个原型,并用new操作符传递给新建的对象呢?

其实,象这样的代码就可以实现这一目标:

function  anyfunc(){};  // 定义一个函数躯壳
anyfunc.prototype  =  Person;  // 将原型对象放到中转站prototype
var  BillGates  =   new  anyfunc();  // 新建对象的内置原型将是我们期望的原型对象

不过,这个anyfunc函数只是一个躯壳,在使用过这个躯壳之后它就成了多余的东西了,而且这和直接使用构造函数来创建对象也没啥不同,有点不爽。

可是,如果我们将这些代码写成一个通用函数,而那个函数躯壳也就成了函数内的函数,这个内部函数不就可以在外层函数退出作用域后自动消亡吗?而且,我们可以将原型对象作为通用函数的参数,让通用函数返回创建的对象。我们需要的就是下面这个形式:

function  New(aClass, aParams)  // 通用创建函数
{
function  new_()  // 定义临时的中转函数壳
{
aClass.Create.apply( this , aParams);  // 调用原型中定义的的构造函数,中转构造逻辑及构造参数
};
new_.prototype  =  aClass;  // 准备中转原型对象
return   new  new_();  // 返回建立最终建立的对象
};

alert(BillGates.constructor

var  Person  =   // 定义的类
{
Create:  function (name, age)
{
this .name  =  name;
this .age  =  age;
},
SayHello:  function ()
{
alert( “ Hello, I’m  “   +   this .name);
},
HowOld:  function ()
{
alert( this .name  +   “  is  “   +   this .age  +   “  years old. “ );
}
}; var  BillGates  =  New(Person, [ " Bill Gates " ,  53 ]);  // 调用通用函数创建对象,并以数组形式传递构造参数
BillGates.SayHello();
BillGates.HowOld(); ==  Object);  // 输出:true

这里的通用函数New()就是一个“语法甘露”!这个语法甘露不但中转了原型对象,还中转了构造函数逻辑及构造参数。

有趣的是,每次创建完对象退出New函数作用域时,临时的new_函数对象会被自动释放。由于new_的prototype属性被设置为新的原型 对象,其原来的原型对象和new_之间就已解开了引用链,临时函数及其原来的原型对象都会被正确回收了。上面代码的最后一句证明,新创建的对象的 constructor属性返回的是Object函数。其实新建的对象自己及其原型里没有constructor属性,那返回的只是最顶层原型对象的构造 函数,即Object。

有了New这个语法甘露,类的定义就很像C#那些静态对象语言的形式了,这样的代码显得多么文静而优雅啊!

转载于:https://www.cnblogs.com/andhm/archive/2011/06/29/2093452.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值