参考整理:http://www.cnblogs.com/seewood/archive/2005/06/24/180740.html
大部分的Javascript的编写者,都只是把它做为简单的脚本引擎,来创建动态的Web页面。同时Web设计人员开始使用在IE浏览器中定义的对象模型,来处理Web页面的内容。但是大多数的开发者并没有认识到Javascript在其自身就具有强大的面向对象的功能。当不使用强类型的时候(变量不必先声明后使用),这种解析性的语言,可以巧妙的达成面向对象(object-oriented)的功能,包括:
- 封装 (Encapsulation)
- 多态 (Polymorphism )
- 继承 (Inheritance)
接下来将会阐述对象在Javascript中,对象是如何被使用,并且如何实现面向对象的。
1.基本概念
在Java语言中,我们可以定义自己的类,并根据这些类创建对象来使用,那么Javascript是否具备这样的功能呢?
是的,Javascript也具有对象的概念,但是它和Java这样面向对象的语言还是有一定的区别的。
2.创建对象
创建对象有很多种方法:
(1)Object
在Javascript中,最简单的可构建的对象,就是机制内建的Object对象。在Javascript中,对象是指定名称的属性(property)的集合。做为解析性语言,Javascript允许给一个对象创建任意个属性,在任何时间(不像C++,它的属性是可以在任何时间添加给对象。它们并不需要事先在对象的声明(definition)或者构造(constructor)中,进行定义)。
所以,举例来说,我们可以创建一个对象,然后添加一系列的属性给它,就像这样:
obj = new Object();
obj.x = 1;
obj.y = 2;
这里,Javascript对象,可以用图形表示成这样的结构:
obj | |
x | 1 |
y | 2 |
prototype properties | |
constructor | function Object |
另外需要注意的是,我们创建的x和y属性, 我们的对象默认有一个属性constructor他指向一个Javascript内部对象函数(funciton)。(prototype,原型在后文会有进一步的说明)
(2)function (构造函数法)
编写一个构造函数,并通过new方式来创建对象,构造函数本可以带有构造参数:
function Obj(){
}
var obj= new Obj();
alert(typeof obj); // 显示 "object"
那么我们再看一下,带公共实例属性的对象,
function Obj(){
this.x = 1;
this.y = 2;
}
obj = new Obj();
可以用图形表示成这样的结构:
obj | |
x | 1 |
y | 2 |
prototype properties | |
constructor | function Obj |
我们还可以在构造函数中传入参数:
function Obj(a,b){
this.x = a;
this.y = b;
}
obj = new Obj(1,2);
alert(obj.x); //1
alert(obj.y); //2
obj2 = new Obj(3,4);
alert(obj2.x); //3
alert(obj2.y); //4
可以用图形表示成我们创建的对象:
obj | |
x | 1 |
y | 2 |
prototype properties | |
constructor | function Obj(a,b) |
obj1 | |
x | 3 |
y | 4 |
prototype properties | |
constructor | function Obj(a,b) |
为了封装对象的行为功能,向调用者隐藏执行过程,我们需要给对象创建方法(method)。Javascript允许你将任意一个函数(function)分配给对象的一个属性。当我们使用 obj.Function 的语法调用函数的时候,将把函数原来定义this的指向,当前这个对象(就像它在构造函数中的那样)。
function Obj(){
this.x = 1;
this.y = 2;
this.Bar = MyMethod;
}
function MyMethod(z){
this.x += z;
}
obj = new Obj();
obj | |
x | 1 |
y | 2 |
Bar | function MyMethod |
prototype properties | |
constructor | function Obj |
现在,我们简单的调用一下,做为对象的方法的Bar函数:
obj.Bar(3);
obj | |
x | 4 |
y | 2 |
Bar | function MyMethod |
prototype properties | |
constructor | function Obj |
所以,你可以方便的给对象定义构造函数和方法,使其对调用者而言,隐藏它的实现过程。同样的,因为,Javascript不是强类型的,所以,我们可以通过定义有相同名字的方法的对象,来简单的实现多态性(polymorphism)。
(3)prototype
试想一下,这是很笨的办法,每次我们都要创建名称没有使用意义的方法函数,然后在构造函数里,把它们分配给每个方法属性。其实,我发现使用Javascript的原型(prototype)机制,是更为直接的方法。
每个对象,可以参照一个原型对象,原型对象包含有自己的属性。它就好比是一个对象定义的备份。当代码,引用一个属性的时候,它并不存在于对象本身里,那么Javascript将会自动的在原型的定义中查找这个属性。而且,事实上,一个对象的原型对象又可以参照另外一个原型对象,就这样以链式最终关联到基类对象的构造函数。(对于DOM对象等系统的对象,原型对象可以修改,但是不可以赋值改变的,只有自定义对象可以。)这是template模型(模板方法,《设计模式》中行为模式的一种),它可以简化我们对方法的定义,同时也可以产生强大的继承机制。
在Javascript中,原型对象是被分配给构造函数的。所以,为了修改对象的原型,必须首先修改构造函数的原型对象的成员。然后,当对象从构造函数被构造的时候,对象将会引用到构造函数的原型。
function Foo(){
this.x = 1;
}
Foo.prototype.y = 2;
obj = new Foo;
document.write('obj.y = ' + obj.y);
obj.y = 2;
obj | |||||
x | 1 | ||||
prototype properties | |||||
constructor | function Foo
|
||||
y | 2 |
即使我们并没有直接的把y属性分配给obj,obj对象仍然有一个y属性。当我们引用obj.y的时候,Javascript实际返回obj.constructor.prototype.y的引用。我们可以肯定的是,原型的值的改变,也将会反映到对象中。
Foo.prototype.y = 3;
document.write('obj.y = ' + obj.y);
obj.y = 3
obj | |||||
x | 1 | ||||
prototype properties | |||||
constructor | function Foo
|
||||
y | 3 |
我们也可以发现,一旦我们初始化一个属性的“私有”(private )的值,存放在原型中的值并不会收到影响:
obj.y = 4;
Foo.prototype.y = 3;
obj | |||||
x | 1 | ||||
y | 4 | ||||
prototype properties | |||||
constructor | function Foo
|
原型方法的命名(Prototype Method Naming)
function Foo(){
this.x = 1;
}
function Foo.prototype.DoIt(){
this.x++;
}
obj = new Foo;
obj.DoIt();
obj | |||||
x | 2 | ||||
prototype properties | |||||
constructor | function Foo
|
||||
DoIt | function Foo.prototype.DoIt |
(4)对象直接量创建对象(json)
JSON(JavaScript Object Notation)是一种优美的JavaScript对象创建方法。JSON也是一种轻量级数据交换格式。JSON非常易于人阅读与编写,同时利于机器解析与生成。JSON是在AJAX中代替XML交换数据的更佳方案。
JSON定义法类似于直接定义法,JSON定义法就是将直接定义法定义的函数与属性放到大括号中,并且去掉属性与函数签名的对象名,把等于号改为了冒号,每行后面改为逗号!
var jsonobject=
{
//对象内的属性语法(属性名与属性值是成对出现的)
propertyname:value,
//对象内的函数语法(函数名与函数内容是成对出现的)
functionname:function(){...;}
};
- jsonobject -- JSON对象名称
- propertyname -- 属性名称
- functionname -- 函数名称
- 一对大括号,括起多个"名称/值"的集合
- JSON使用"名称/值"对的集合表示,也可以被理解为数组(Array)
- 属性名或函数名可以是任意字符串,甚至是空字符串(见下面示例)
- 逗号用于隔开每对"名称/值"对
引用网址: http://www.dreamdu.com/javascript/json/
var site =
{
URL : "www.dreamdu.com",
name : "梦之都",
englishname : "dreamdu",
author : "可爱的猴子",
summary : "免费的网页设计教程",
pagescount : 100,
isOK : true,
startdate : new Date(2005, 12),
say : function(){document.write(this.englishname+"say : hello world!")},
age : function(){document.write(this.name+"已经"+((new Date().getFullYear())-this.startdate.getFullYear())+"岁了!")}
};
嵌套JSON对象定义
var sites =
{
count: 2,
language: "chinese",
baidu:
{
URL: "www.baidu.com",
name: "百度",
author: "baidu",
say : function(){document.write(this.name+" say hello")}
},
dreamdu:
{
URL: "www.dreamdu.com",
name: "梦之都",
author: "monkey",
say : function(){document.write(this.name+" say hello")}
}
};
实例见: http://www.dreamdu.com/javascript/exe_json/
3.对象属性
(1)JS中可以为对象定义三种类型的属性:私有属性、实例属性和类属性,
与Java类似,私有属性只能在对象内部使用,实例属性必须通过对象的实例进行引用,而类属性可以直接通过类名进行引用。
(2)私有属性
私有属性只能在构造函数内部定义与使用。
语法格式:var propertyName=value;
例如:
function User(age){
this.age=age;
var isChild=age<12;
this.isLittleChild=isChild;
}
var user=new User(15);
alert(user.isLittleChild);//正确的方式
alert(user.isChild);//报错:对象不支持此属性或方法
(3)实例属性,存在两种方式:
prototype方式,语法格式:functionName.prototype.propertyName=value
this方式,语法格式:this.propertyName=value,注意后面例子中this使用的位置
上面中value可以是字符串、数字和对象。
例如:
function User(){ }
User.prototype.name=“user1”;
User.prototype.age=18;
var user=new User();
alert(user.age);function User(name,age,job){
—————————————–
this.name=“user1”;
this.age=18;
this.job=job;
}
alert(user.age);
(4)类属性
语法格式:functionName.propertyName=value
例如:
function User(){ }
User.MAX_AGE=200;
User.MIN_AGE=0;
alert(User.MAX_AGE);
参考JS标准对象的类属性:
Number.MAX_VALUE //最大数值 Math.PI //圆周率