刚接触JavaScript时,很多书上都强调一个概念:JavaScript仅仅是基于对象(Object-Based)的语言。怎么解释这个“基于对象”,我理解为是JavaScript对面向对象语言的基本特征(自定义类,封装,继承,覆盖,多态)支持不够。JavaScript日常编程中很少去创建自己的类,语言本身提供了丰富的对象类型,并且自动创建了大量的对象供我们使用。但是Javascript也同样提供一些面向对象语言(Object-Oriented)的特性,比如定义类,支持继承等等,这些特性是平时不太用到的。下面先从不通角度对JavaScript对象的分下类别。

一,静态对象和动态对象
  在Javascript编程时你会发现,很多对象是不用去new的,比String对象,Math对象。比如使用Math四舍五入,直接调用Math.round(),这看起来很像调用Java中类的静态方法,但在JavaScript中这叫静态对象,像是在玩感念,不知道内部实现有没有什么相似之处。动态对象上是需要new的,比如:new Date(),new Array();此类对象之所以要new,是因为创建新的对象的状态需要制定,即需要传入参数。静态对象基本要么不需要参数,要么不需要我们提供。根据我们自己的类创建的对象,也划到动态对象里吧。

二,内部对象,浏览器对象,DHTML对象,自定义对象
  JavaScript提供的内部对象多用于计算,有:String,Date,Math,Array...;浏览器对象由浏览器提供,通过这些对象可以操纵浏览器,JavaScript可以直接引用:window,document,history...;DHTML对象,简单理解就是把HTML对象解析成DOM树,通过DHTML对象可以动态操纵HTML,CSS元素:table,form,image...;自定义对象,作者自己根据自定义类创建的对象,一般很少用到。

  前面提到JavaScript称不上是面向对象的语言,相对于Java这样纯面向对象的语言,她提供的面向对象编程(OOP)支持相对弱了许多,下面从面向对象的一些基本特征入手与Java比较一番。
一,自定义类
  类是一种蓝图,对象是根据这个蓝图创建的“实物”,经典的比喻是图纸和大厦。Java可以非常方便的自定义类,提供的支持包括:包,类的可见修饰(public,缺省),抽象类,final类,内部类,匿名类(内部类也可以是静态的),类的域和方法,以及接口(需要注意的是接口不继承Object,但她的实现类会继承Object。虚拟机规范中指出,接口不会隐藏Object类的方法)等。JavaScript语言只提供简单的自定义类(有些书中把这叫做自定义对象,是不准确的)的方法:

function cat(name) {
 this.name = name;
 this.talk = function() {
    alert( this.name + " say meeow!" );
       }
 }  cat1 = new cat("felix");
 cat1.talk();


  JavaScript里,一般把类叫做对象的原型,也有叫构造器函数的,原型用fonction定义,它的属性和方法在函数体里用this来定义,并用new来实例对象。可能也支持内部类。看得出与Java相比,单薄了许多,但JavaScript有一个功能是Java没有得,就是通过prototype属性,在原型里增加方法。

cat.prototype.changeName = function(name) {
     this.name = name;
    }
 cat2 = new cat("pursur");
 cat2.changeName("Bill");
 cat2.talk();


  可以看出,新定义得对象中,增加了changeName()方法(不知道cat1中也增加了这个方法吗?我猜应该也增加了,有空试试)。这个方法被所有的改原型得实例共享。prototype也可以对其他非自定义原型工作,比如

String.prototype.half=function(){
     return --half String;
   }


  JavaScript管这叫用原型(prototype)重载JavaScript对象
二,封装
  封装,就好比机顶盒,把主要的部件都封装在一个盒子里面,对外暴露几个输入输出接口。Java得封装是限制了域和方法得可见范围。这中封装,不仅仅是利用域和方法的修饰符(public,private,protected,dufalt)来实现,通过多态,也可以屏蔽子类对象的方法。举例如下:

interface Teacher{
  void teach();
 }
 interface Playactor {
  void play();
 }
 class Liuyapeng implementTeacher, Playactor {
  public joke() {
  }
 }
 ...
 Liuyapeng liuyapeng = new Liuyapeng();
 Teacher teacher = new Liuyapeng();
 Playactor playactor = new Liuyapeng();
 ...


  这三个方法都是public修饰符,但teacher只能看到teach(),playactor只能看到play(),liuyapeng能看到三个方法。虽说Java中没有多继承,但一个类有多个角色,我管这叫由多角色引起的封装。
  JavaScript中没有修饰符,没有多继承,也没有多角色。JavaScript原型的方法和属性都是可见的。所以JavaScript其实没有封装,更像是把关联的变量和方法打包在一起,然后用new来分配空间。当然想我们这样深受面向对象思想“毒害”的一代Coder来说,看成简单版本的有充分安全感的对象,更有符合思维习惯。
三,继承
  Java中只有单继承,但可有有多实现(多角色-我喜欢这么叫)。Java的继承还涉及到父类域和方法继承后的可见性(注意,父类的域和方法都被继承下来,只是有些在子类中是不能直接看到,可有用super.xxx来访问。创建子类对象是,父类中那些不可见的域也是要分配空间的。)。JavaScript也支持继承,但不涉及到可见性和多实现。一下是JavaScript关于继承的一段引文:
In Java and C++, there is an explicit concept of the class hierarchy. i.e. Every class can have a super class from which it inherits properties and methods. Any class can be extended, or sub-classed so the resulting subclass can inherit its parent's behavior. As we have seen, javascript supports prototype inheritance instead of class based. It's possible for inheritance to happen other ways, however.

The following is an example of inheritance through functions.
 <script language="javascript" type="text/javascript">
     <!--
  // thanks to webreference
  function superClass() {
   this.supertest = superTest; //attach method superTest
  }  function subClass() {
   this.inheritFrom = superClass;
   this.inheritFrom();
   this.subtest = subTest; //attach method subTest
  }  function superTest() {
   return "superTest";
  }  function subTest() {
   return "subTest";
  }  var newClass = new subClass();
  alert(newClass.subtest()); // yields "subTest"
  alert(newClass.supertest()); // yields "superTest"   -->
 </script>

四,覆盖
  Java中覆盖(OverWrite)和重载(OverLoad)是两个不通的概念,覆盖发生在子类和父类之间,并且方法名,参数列表和返回类型严格相同(在jdk1.5版本中子类方法的返回类型可以是父类方法返回类型的子类--待求证)。
  JavaScript中没有覆盖和重载的概念。
五,多态
  多态是个好东西,她能让你的程序更智能。有了继承和覆盖才会有多态,在Java中,多态有编译时多态和运行时多态的区别,编译时多态和方法的重载有关。运行时多态,包含两个概念,一是:子类型对象和父类型兼容。二是:会优先查找对象中覆盖的方法并执行,你提供的仅仅是引用变量的类型中的那个方法的签名。累啦就不举例子啦。
  JavaScript连覆盖都没有,就谈不上多态啦。
  通过上述比较,很明显看出JavaScript仅支持类(原型)和类(原型)的继承。所以也谈不上面向对象的语言。不过JavaScript依然是很成功的语言,使用她可以很轻松的左右浏览器的行为,实现动态交互页面,验证表单数据数据。JavaScrit提供自定义类型的功能虽然相对较弱,但利用起来也还顺手。下面搜集一下JavaScript自定义对象方法和使用的技巧,和大家交流。

一,自定义对象的方法--摘至网络
  1,用 new Object() 来创建对象
 在javascript里有几种创建对象的方法,在不同的场合可用不同的方法.最简单的就是用 new 操作符,例如:

<script language="javascript" type="text/javascript">
   <!--
  person = new Object()
  person.name = "Tim Scarfe"
  person.height = "6Ft"
  person.run = function() {
    this.state = "running"
    this.speed = "4ms^-1"
   }
   -->
 </script>


 我们在这个例子里定义了person这个对象,然后加入了它的属性和方法.在这个例子里,自定义的方法里有两个属性。
  2,用文字记号(Literal Notation)创建对象
 用文字记号也可以创建对象,但要javascript 1.2以上版本.它的创建形式是多样的。

<script language="javascript" type="text/javascript">
    <!--
  // Object Literals
  timObject = {
   property1 : "Hello",
   property2 : "MmmMMm",
   property3 : ["mmm", 2, 3, 6, "kkk"],
   method1 : function(){alert("Method had been called" + this.property1)}
  };
  timObject.method1();
  alert(timObject.property3[2]) // will yield 3  // another example
  var circle = { x : 0, y : 0, radius: 2 } 
  // nesting is no problem.
  var rectangle = { 
   upperLeft : { x : 2, y : 2 },
   lowerRight : { x : 4, y : 4}
  }
  alert(rectangle.upperLeft.x) // will yield 2
      //-->
 </script>


 文字记号可是是数组,也可以是任意的javascript表达式或值。
  3,通过构造器函数创建对象并通过prototype修改y原型的方法和属性--前面已经介绍。
  在仅仅定义单个对象是第一、二种方法更灵活,属性太多的话,在定义一组有相同属性和方法的对象时,第三钟更有效。
二,使用技巧
  1,使用对象把一组相关的变量集中起来。
  2,使用for in和联合数组遍历属性。

<script language="javascript" type="text/javascript">
   <!--
  var testObj = {
  prop1 : "hello",
  prop2 : "hello2",
  prop3 : new Array("hello",1,2)
  };
  for(x in testObj) {
   alert( x + "-" + testObj[ x ] );
  }
   -->
 </script>