面向对象目标
我假设读者对JavaScript有基本的了解,包括事件回调,并且了解面向对象编程。
我认为面向对象编程的三个主要的目标是:
² 封装 提供一个方法,去调用JavaScript对象里边的成员
² 多态 两个类响应同样一个方法
² 继承 定义一个类的子类
通过以下例子,我将演示如下技术:
定义一个类
定义类里边的回调方法
定义一个子类
从子类调用基类的构造函数
在子类中重写基类的方法
在子类中调用基类的方法
简单对象
在JavaScript中,最简单的对象就是构建一个Object的数据类型。在JavaScript中,可以把一组命名后的属性集合放在一块儿执行。作为一种解释型语言,JavaScript允许你在任何地方任何时间去创建属性。
下面,我们举一个例子,首先创建一个对象,然后添加多个属性给这个对象:
obj = new Object;
obj.x = 1;
obj.y = 2;
我用如下的图形表示JavaScript对象:
obj | |
x | 1 |
y | 2 |
Object.prototype | |
constructor | Object |
其中,左列显示的是对象的每个可用的属性,右列显示的值。在这个里边,其实我们定义了一个JavaScript内置的构造函数,包含两个属性。在后边,我会解释prototype这个属性的。
定义一个类
一个方法可以很容易定义出一个JavaScript类。下面的代码片段定义了一个类 foo,然后,创建了这个类的对象。
function Foo()
{
this.x = 1;
this.y = 2;
}
obj = new Foo;
obj | |
x | 1 |
y | 2 |
Foo.prototype | |
constructor | Foo |
Object.prototype | |
(constructor) | Object |
只要你愿意,你可以创建很多个Foo类型的对象,它们分别会初始化各自的属性,将x 与 y赋值为1和2.
解释prototypes
在JavaScript中,每一个对象都可以从其它的对象进行继承,我们称之为prototype。当执行到某属性时,JavaScript会首先直接从该对象中寻找是否具有,如果没有,那么就在对象的object prototype中寻找该属性,像一条锁链一样,一直追溯到根原型(root prototype).
例如,我们希望创建一个对象object,X来自于方法B,B的原型是B.prototype, A.prototype, Object.prototype:
我们可以用下面的代码表示:
Object.prototype.inObj = 1;
function A()
{
this.inA = 2;
}
A.prototype.inAProto = 3;
B.prototype = new A; // Hook up A into B's prototype chain
B.prototype.constructor = B;
function B()
{
this.inB = 4;
}
B.prototype.inBProto = 5;
x = new B;
document.write(x.inObj + ', ' + x.inA + ', ' + x.inAProto + ', ' + x.inB + ', ' + x.inBProto);
1, 2, 3, 4, 5
x | |
inB | 4 |
B.prototype | |
constructor | B |
inA | 2 |
inBProto | 5 |
A.prototype | |
(constructor) | A |
inAProto | 3 |
Object.prototype | |
(constructor) | Object |
inObj | 1 |
定义并且调用类的方法
function Foo()
{
this.x = 1;
}
Foo.prototype.AddX = function(y) // Define Method
{
this.x += y;
}
obj = new Foo;
obj.AddX(5); // Call Method
obj | |
x | 6 |
Foo.prototype | |
constructor | Foo |
AddX | function ... |
Object.prototype | |
(constructor) | Object |
多态
function A()
{
this.x = 1;
}
A.prototype.DoIt = function() // Define Method
{
this.x += 1;
}
function B()
{
this.x = 1;
}
B.prototype.DoIt = function() // Define Method
{
this.x += 2;
}
a = new A;
b = new B;
a.DoIt();
b.DoIt();
document.write(a.x + ', ' + b.x);
2, 3
a | |
x | 2 |
A.prototype | |
constructor | A |
DoIt | function ... |
Object.prototype | |
(constructor) | Object |
b | |
x | 3 |
B.prototype | |
constructor | B |
DoIt | function ... |
Object.prototype | |
(constructor) | Object |
定义一个子类
function A() // Define super class
{
this.x = 1;
}
A.prototype.DoIt = function() // Define Method
{
this.x += 1;
}
B.prototype = new A; // Define sub-class
B.prototype.constructor = B;
function B()
{
A.call(this); // Call super-class constructor (if desired)
this.y = 2;
}
B.prototype.DoIt = function() // Define Method
{
A.prototype.DoIt.call(this); // Call super-class method (if desired)
this.y += 1;
}
b = new B;
document.write((b instanceof A) + ', ' + (b instanceof B) + '
');
b.DoIt();
document.write(b.x + ', ' + b.y);
true, true
2, 3
b | |
x | 2 |
y | 3 |
B.prototype | |
constructor | B |
(x) | 1 |
DoIt | function ... |
A.prototype | |
(constructor) | A |
(DoIt) | function ... |
Object.prototype | |
(constructor) | Object |
An Alternate Sub-Classing Paradigm
Function.prototype.DeriveFrom = function(fnSuper)
{
var prop
if (this == fnSuper)
{
alert("Error - cannot derive from self");
return;
}
for (prop in fnSuper.prototype)
{
if (typeof(fnSuper.prototype[prop]) == "function" && !this.prototype[prop])
{
this.prototype[prop] = fnSuper.prototype[prop];
}
}
this.prototype[fnSuper.StName()] = fnSuper;
}
Function.prototype.StName = function()
{
var st;
st = this.toString();
st = st.substring(st.indexOf(" ")+1, st.indexOf("("));
if (st.charAt(0) == "(")
st = "function ...";
return st;
}
Function.prototype.Override = function(fnSuper, stMethod)
{
this.prototype[fnSuper.StName() + "_" + stMethod] = fnSuper.prototype[stMethod];
}
Repeating the sub-classing example using this new paradigm:
function A() // Define super class
{
this.x = 1;
}
A.prototype.DoIt = function() // Define Method
{
this.x += 1;
}
B.DeriveFrom(A); // Define sub-class
function B()
{
this.A(); // Call super-class constructor (if desired)
this.y = 2;
}
B.Override(A, 'DoIt');
B.prototype.DoIt = function() // Define Method
{
this.A_DoIt(); // Call super-class method (if desired)
this.y += 1;
}
b = new B;
document.write((b instanceof A) + ', ' + (b instanceof B) + '
');
b.DoIt();
document.write(b.x + ', ' + b.y);
false, true
2, 3
b | |
x | 2 |
y | 3 |
B.prototype | |
constructor | B |
DoIt | function ... |
A | A |
A_DoIt | function ... |
Object.prototype | |
(constructor) | Object |
私有成员
令人吃惊的是,JavaScript支持对象的私有成员。
function A()
{
var x = 7;
this.GetX = function() { return x;}
this.SetX = function(xT) { x = xT; }
}
obj = new A;
obj2 = new A;
document.write(obj.GetX() + ' ' + obj2.GetX());
obj.SetX(14);
document.write(' ' + obj.GetX() + ' ' + obj2.GetX());
7 7 14 7
obj | |
GetX | function ... |
SetX | function ... |
A.prototype | |
constructor | A |
Object.prototype | |
(constructor) | Object |
obj2 | |
GetX | function ... |
SetX | function ... |
A.prototype | |
constructor | A |
Object.prototype | |
(constructor) | Object |
Trackback: http://mckoss.com/jscript/object.htm
http://www.cnblogs.com/johnson2008/archive/2008/05/15/1198252.html
http://www.cnblogs.com/johnson2008/archive/2008/05/29/1209781.html