JavaScript 的物件導向
最簡單的物件
範例: people.js
var People={
name:"john",
age:30,
print:function() {
console.log("name=", this.name, "age=", this.age);
}
}
People.print();
執行結果:
$ node people.js
name= john age= 30
圓形物件
範例: circle.js
var circle = {
r:3,
area:function() {
return 3.14*this.r*this.r;
}
}
console.log("circle.r=%d", circle.r);
console.log("circle.area()=%d", circle.area());
執行結果
NQU-192-168-60-101:ccc csienqu$ node circle.js
circle.r=3
circle.area()=28.259999999999998
圓形類別 (ES6 新語法)
class Circle {
constructor(r) {
this.r = r
}
area() {
return 3.14*this.r*this.r;
}
}
var c1 = new Circle(1)
console.log("c1.r=%d", c1.r);
console.log("c1.area()=%d", c1.area());
var c2 = new Circle(2)
console.log("c2.area()=%d", c2.area());
執行結果
csienqu-teacher:object csienqu$ node circleClass
c1.r=1
c1.area()=3.14
c2.area()=12.56
複數的範例
ES6 新版的類別寫法
檔案: ComplexClass.js
class Complex {
constructor(r,i) {
this.r = r;
this.i = i;
}
add(c2) {
return new Complex(this.r+c2.r, this.i+c2.i);
}
sub(c2) {
return new Complex(this.r-c2.r, this.i-c2.i);
}
mul(c2) {
return new Complex(this.r*c2.r-this.i*c2.i,
this.r*c2.i+this.i*c2.r);
}
toString() {
return this.r+"+"+this.i+"i"
}
}
var a=new Complex(1,2), b=new Complex(2,1);
var x = a.add(b).sub(b).mul(b);
console.log("a=%s", a);
console.log("b=%s", b);
console.log("a.add(b)=%s", a.add(b));
console.log("a.sub(b)=%s", a.sub(b));
console.log("a.mul(b)=%s", a.mul(b));
console.log("x=%s", x);
執行結果:
$ node ComplexClass.js
a=1+2i
b=2+1i
a.add(b)=3+3i
a.sub(b)=-1+1i
a.mul(b)=0+5i
x=0+5i
不管你總共建立了多少 Complex 物件, Complex 的 prototype 都只會有一份,因此這種寫法會比前一種寫法更省記憶體。
而這種寫法,也是最經典的 javascript 物件導向寫法。
在一般的物件導向語言裡,會有《繼承》的機制,但是在 javascript 的早期版本 (ES6 之前) 裡面,並沒有《繼承》的機制。
但是、javascript 仍然可以做到類似《繼承》的功能,方法是在原型裏再塞入原型,這種原型裡面還可以有原型的做法,真的是非常美妙的一種設計阿!
習題
1 請寫出一個具有加減乘除運算的複數物件? (Complex, add, sub, mul, div) (除法可以不寫,算加分題)
提示:第一題請參考本章內文
2 請寫出一個具有『加、減、內積、負』的向量物件? (Vector, add, sub, dot, neg)
提示:第二題架構如下:
class Vector {
add(v2) { ... }
sub(v2) { ... }
dot(v2) { ... }
neg() { ... }
}
3 請寫一組物件,包含《矩形、圓形》與抽象的形狀,每個物件都具有 area() 函數可以計算其面積? (Shape.area(), Rectangle, Circle)
提示:第三題架構如下:
class Shape {
}
class Circle {
constructor(radius) {...}
area() { ... }
}
class Rectangle {
constructor(width, height) {...}
area() { ... }
}
4 請寫一組物件,包含『浮點數,有理數,複數』,這三個都繼承『數』這個物件,而且每個都具有 add, sub, mul, div, power 等成員函數!
提示:第四題的架構如下:
class Number {
power(n) {
var p = this;
for (var i=1; i<n; i++) {
p = p.mul(this);
}
return p;
}
}
class Float extends Number {
add(o2) { ...}
sub(o2) { ...}
mul(o2) { ...}
div(o2) { ...}
toString() {... }
}
class Rational extends Number {
add(o2) { ...}
sub(o2) { ...}
mul(o2) { ...}
div(o2) { ...}
toString() {... }
}
class Complex extends Number {
add(o2) { ...}
sub(o2) { ...}
mul(o2) { ...}
div(o2) { ...}
toString() {... }
}
第四題不含有理數與浮點數,只有 Number 和 Complex 的版本如下:
class Number {
power(n) {
var p = this;
for (var i=1; i<n; i++) {
p = p.mul(this);
}
return p;
}
}
class Complex extends Number {
constructor(r,i) {
super(r,i);
this.r = r;
this.i = i;
}
add(c2) {
return new Complex(this.r+c2.r, this.i+c2.i);
}
sub(c2) {
return new Complex(this.r-c2.r, this.i-c2.i);
}
mul(c2) {
return new Complex(this.r*c2.r-this.i*c2.i,
this.r*c2.i+this.i*c2.r);
}
toString() {
return this.r+"+"+this.i+"i"
}
}
var a=new Complex(1,2), b=new Complex(2,1);
var x = a.add(b).sub(b).mul(b);
console.log("a=%s", a);
console.log("b=%s", b);
console.log("a.add(b)=%s", a.add(b));
console.log("a.sub(b)=%s", a.sub(b));
console.log("a.mul(b)=%s", a.mul(b));
console.log("x=%s", x);
console.log("a.power(3)=%s", a.power(3));