prototype的一个优势也是缺

如何在 Javascript 实现 OO 编程?恐怕最好的方式就是充分利用 prototype 属性。关于 prototype 的介绍有很多,我就不赘述了。比较基本的原理是,当你用 prototype 编写一个类后,当你 new 一个新的 object ,浏览器会自动把 prototype 中的内容替你附加在 object 上。这样,通过利用 prototype ,你也就实现了类似 OO Javascript

Javascript 中, object 就是一个 associative array 。一个 function 就是一个类。当你编写如下 function 时,其实就是定义了一个类,该 function 就是它的构造函数。

function MyObject(name, size)

       {

              this.name = name;

              this.size = size;

       }

之后,你可以方便的通过 MyObject 类的 prototype 属性来方便的扩充它。比如,你可以给他添加其他的属性和方法。

       MyObject.prototype.tellSize = function()

       {

              return "size of "+this.name+" is "+this.size;

       }

      

       MyObject.prototype.color = "red";

       MyObject.prototype.tellColor = function()

       {

              return "color of "+this.name+" is "+this.color;

       }

      

       var myobj1 = new MyObject("tiddles", "7.5 meters");

       domDiv.innerHTML += myobj1.tellColor()+"<br /><br />";

你可以想象,当你调用 tellColor() 方法后,结果是这样的:

color of tiddles is red

很方便的是, prototype 属性可以动态添加。比如,你需要往 MyObject 中加入一个 height 属性,并希望其提供一个 tellHeight() 方法来获得 height 属性的值。你可以在上面的代码后,继续添加如下的代码:

       MyObject.prototype.height = "2.26 meters";

       MyObject.prototype.tellHeight = function()

       {

              return "height of "+this.name+" is "+this.height;

       }

之后,你可以访问一下 myobj1 tellHeight() 方法,你可以得到如下的结果:

height of tiddles is 2.26 meters

prototype 的这些动态的特性看起来有些迷人,不过我倒是反而觉得有些凉飕飕的。确实,这些特性给你很大的灵活性,可以给与你 runtime 改变类属性和方法的能力。不过,稍微发掘一下,会有些不良的习惯产生。

首先,如果可以动态添加属性和方法,那么很容易让人想到,当我调用时,我想要调用的属性或者方法存在不?这是一个很严肃的问题,如果当我们调用时根本没有该属性或者方法,将可能导致我们的脚本 down 掉。

不过也有解决办法。比如,在上面的代码中,当还没有 tellHeight() 方法时,我们可以如下编写代码避免发生错误:

       if (myobj1.tellHeight)

       {

              domDiv.innerHTML += myobj1.tellHeight()+"<br /><br />";

       }

注意,一定要在 if 语句中,不要加方法后面的那对 () ,否则,直接就 down 掉了。有兴趣的读者可以打印一下,看看分别访问 myobj1.tellHeight myobj1.tellHeight() 时有什么区别。

也许,你觉得这个是小意思。加个判断嘛,不就好了?

对,但是下面一个问题更令人头痛。

属性和方法在不在的问题简单,可是属性和方法变不变化的问题可就严重了。在不在我们可以检测,变不变呢?比如,请看下面的代码:

       function MyObject(name, size)

       {

              this.name = name;

              this.size = size;

       }

      

       MyObject.prototype.color = "red";

       MyObject.prototype.tellColor = function()

       {

              return "color of "+this.name+" is "+this.color;

       }

      

       var myobj1 = new MyObject("tiddles", "7.5 meters");

       domDiv.innerHTML += myobj1.tellColor()+"<br /><br />";

      

       MyObject.prototype.color = "green";

      

       domDiv.innerHTML += myobj1.tellColor()+"<br /><br />";

该代码将产生如下结果:

color of tiddles is red
color of tiddles is green

请注意,你修改的是类 MyObject color 属性。但是你惊奇的看到你之前实例化的对象 myobj1 的属性值竟然也变化了。天!如果你的项目代码是多人合作,那么,也许某个人会在编程时为了图一己之便,擅自修改你的类。于是,所有人的对象都变化了。于是,你们陷入了漫长的 debug 过程中。。。。。。(不要说我没有告诉你啊)

上面是属性,还有方法:

       function MyObject(name, size)

       {

              this.name = name;

              this.size = size;

       }

      

       MyObject.prototype.color = "red";

       MyObject.prototype.tellColor = function()

       {

              return "color of "+this.name+" is "+this.color;

       }

      

       var myobj1 = new MyObject("tiddles", "7.5 meters");

       domDiv.innerHTML += myobj1.tellColor()+"<br /><br />";

      

       MyObject.prototype.color = "green";

       MyObject.prototype.tellColor = function()

       {

              return "your color of "+this.name+" is "+this.color;

       }

      

       domDiv.innerHTML += myobj1.tellColor()+"<br /><br />";

这段代码的结果是:

color of tiddles is red
your color of tiddles is green

哈?原来方法也能变,汗!

问题来了。 Javascript 太灵活的编程方式多少让人不适应。如果整个 Team 的水平都比较高还可以,没人会犯这样的错误。但是,当有个毛头小伙子不知情,擅自修改类,将导致所有的人的对象都发生变化,无论是属性还是方法。在 Javascript 代码变得越来越多的 Ajax 时代,这是一个严重的问题。

这说明,编写 Javascript 时,好的编程风格更加重要。记得某人曾经说过这样的话,想 Java C# 这些比较严格的语言,虽然降低了灵活性,但也减少了犯错误的可能。这样,即使一个新手,他写出的代码也不会与高手差太多。但是,像 Javascript 这样的脚本语言,由于太灵活,所以,高手写出的是天使,而新手写的,可能是魔鬼!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值