Java寫久了以後,對於物件導向的程式寫法已經感到非常自然,
開始接觸Javascript以後,在程式設計上常常覺得窒礙難行,
覺得如果可以用物件該有多好啊!
The Node Craftsman Book是Manuel Kiessling的第二本書,
(第一本是The Node Beginner Book - A comprehensive Node.js tutorial,非常推薦新手完讀)
其中一個章節很完整的介紹了幾種達到類似效果的"模擬"物件導向寫法,
整理記錄在這邊
==========我是分隔線==========
我們要來談一個叫做myCar的物件。
myCar就是一台車子,簡單來說,它有drive跟honk的功能。
在Java裡,要表達這輛車子很簡單(吧)
我們會定義一個Car的class,
class裡有兩個函數,一個是drive,一個是honk。
接著只要將myCar定義為Car的物件,我就可以讓myCar按下喇叭
Car myCar = new Car();
myCar.honk();
那在Javascript裡呢?
最簡單的方法是定義makeCar函數,這個函數會回傳具有honk動作的車子物件,要幾個就有幾個:
var makeCar = function() {
var newCar = {};
newCar.honk = function() {
console.log('honk honk');
};
return newCar;
};
myCar1 = makeCar();
myCar2 = makeCar();
這個方法有一個最大的特色,就是製造出來的每輛車子都互相獨立(indepedent),不共享任何東西。也就是說,當你產生1,000輛車子時,Javascript的編譯器也就存了1,000份一模一樣的honk函數在記憶體裡面。當你需要大量複製使用物件時,這會是非常耗記憶體的作法!
在Javascript裡,constructor是一個特別的函數,專門用來產生具有共同行為的物件。這種產生物件的方式其實已經很接近Java裡class的概念,因此它又稱為pseudo class。
constructor的用法是這樣的:
var Car = function() {
this.honk = function() {
console.log('honk honk');
};
};
var myCar = new Car();
console.log(myCar.constructor); // outputs [Function: Car]
Car是constructor函數,使用this可以定義物件共同的行為,使用new就可以產生物件。
直接從prototyping的用法開始介紹:
var Car = function() {};
var.prototype.honk = function() {
console.log('honk honk');
};
var myCar = new Car();
Car是一個空的constructor function。在Javascript中,函數也是一種物件,所以函數也具有propoties。prototype就是constructor的其中一個propoty,讓我們可以定義honk成為Car共享的函數。
如果現在我想讓myCar按喇叭(myCar.honk()),Javascript執行的流程是這樣的:在myCar物件尋找honk函數來執行,如果找不到的話,就從myCar的prototype裡找。
這樣的流程讓honk的定義具有一些彈性,例如:
var Car = function() {};
Car.prototype.honk = function() {
console.log('honk honk');
};
var myCar = new Car();
myCar.honk(); // executes Car.prototype.honk() and outputs "honk honk"
Car.prototype.honk = function() {
console.log('meep meep');
};
myCar.honk(); // executes Car.prototype.honk() and outputs "meep meep"
var Car = function() {};
Car.prototype.honk = function() {
console.log('honk honk');
};
var myCar = new Car();
Car.prototype.drive = function() {
console.log('vrooom...');
};
myCar.drive(); // executes Car.prototype.drive() and outputs "vrooom..."
var Car = function() {};
Car.prototype.honk = function() {
console.log('honk honk');
};
var myCar1 = new Car();
var myCar2 = new Car();
myCar1.honk(); // executes Car.prototype.honk() and outputs "honk honk"
myCar2.honk(); // executes Car.prototype.honk() and outputs "honk honk"
myCar2.honk = function() {
console.log('meep meep');
};
myCar1.honk(); // executes Car.prototype.honk() and outputs "honk honk"
myCar2.honk(); // executes myCar2.honk() and outputs "meep meep"
prototype其實是非常有趣的一種用法,透過一連串的prototype指定,Javascript還可以實現Java中的inheritance概念。
假設我們說Car跟Bike都是一種交通工具(Vehicle),Vehicle共同的行為就是可以駕駛(drive),不過Car有喇叭可按(honk),但Bike是按鈴(ring)。
在Javascript中可以使用prototype來描述這兩種交通工具:
var Vehicle = function() {};
Vehicle.prototype.drive = function() {
console.log('vrooom...');
};
var Car = function() {};
var Bike = function() {};
Car.prototype = new Vehicle();
Bike.prototype = new Vehicle();
Car.prototype.honk = function() {
console.log('honk honk');
};
Bike.prototype.ring = function() {
console.log('ring ring');
};
var myCar = new Car();
var myBike = new Bike();
myCar.drive(); // outputs "vrooom..."
myBike.drive(); // outputs "vrooom..."
myCar.honk(); // outputs "honk honk"
myBike.ring(); // outputs "ring ring"
讓我們直接從Object.create函數的定義開始介紹
Object.create = function(o) {
var F = function() {};
F.prototype = o;
return new F();
};
傳入物件 o,Object.create函數會回傳一個繼承o的constructor函數F。
回到prototype的例子,我們現在使用Object.create來描述一輛屬於交通工具的汽車:
var vehicle = {};
vehicle.drive = function () {
console.log('vrooom...');
};
var car = Object.create(vehicle);
car.honk = function() {
console.log('honk honk');
};
var myCar = Object.create(car);
myCar.honk(); // outputs "honk honk"
myCar.drive(); // outputs "vrooom..."
vehicle是一個具有drive行為的物件,我們使用Object.create產生另一個物件car,除了繼承drive行為以外,我們又賦予它新的honk行為,最後再用一次Object.create產生又能honk又能drive的myCar物件。
這個用法完整呈現了Javascript與Java的不同:Java的物件導向是建立在object-class的關係上,而Javascript則是object-object的概念。透過object-object來實踐物件導向的程式,就稱為Prototype-based programming。
開始接觸Javascript以後,在程式設計上常常覺得窒礙難行,
覺得如果可以用物件該有多好啊!
The Node Craftsman Book是Manuel Kiessling的第二本書,
(第一本是The Node Beginner Book - A comprehensive Node.js tutorial,非常推薦新手完讀)
其中一個章節很完整的介紹了幾種達到類似效果的"模擬"物件導向寫法,
整理記錄在這邊
==========我是分隔線==========
我們要來談一個叫做myCar的物件。
myCar就是一台車子,簡單來說,它有drive跟honk的功能。
在Java裡,要表達這輛車子很簡單(吧)
我們會定義一個Car的class,
class裡有兩個函數,一個是drive,一個是honk。
接著只要將myCar定義為Car的物件,我就可以讓myCar按下喇叭
Car myCar = new Car();
myCar.honk();
那在Javascript裡呢?
1. Using a simple function to create plain objects. 用函數產生物件
最簡單的方法是定義makeCar函數,這個函數會回傳具有honk動作的車子物件,要幾個就有幾個:
var makeCar = function() {
var newCar = {};
newCar.honk = function() {
console.log('honk honk');
};
return newCar;
};
myCar1 = makeCar();
myCar2 = makeCar();
這個方法有一個最大的特色,就是製造出來的每輛車子都互相獨立(indepedent),不共享任何東西。也就是說,當你產生1,000輛車子時,Javascript的編譯器也就存了1,000份一模一樣的honk函數在記憶體裡面。當你需要大量複製使用物件時,這會是非常耗記憶體的作法!
2. Using a constructor function to create objects. 定義一個建構函數來製造物件
在Javascript裡,constructor是一個特別的函數,專門用來產生具有共同行為的物件。這種產生物件的方式其實已經很接近Java裡class的概念,因此它又稱為pseudo class。
constructor的用法是這樣的:
var Car = function() {
this.honk = function() {
console.log('honk honk');
};
};
var myCar = new Car();
console.log(myCar.constructor); // outputs [Function: Car]
Car是constructor函數,使用this可以定義物件共同的行為,使用new就可以產生物件。
3. Using prototyping to efficiently share behavior between objects. 使用prototyping. 定義物件共享的行為
直接從prototyping的用法開始介紹:
var Car = function() {};
var.prototype.honk = function() {
console.log('honk honk');
};
var myCar = new Car();
Car是一個空的constructor function。在Javascript中,函數也是一種物件,所以函數也具有propoties。prototype就是constructor的其中一個propoty,讓我們可以定義honk成為Car共享的函數。
如果現在我想讓myCar按喇叭(myCar.honk()),Javascript執行的流程是這樣的:在myCar物件尋找honk函數來執行,如果找不到的話,就從myCar的prototype裡找。
這樣的流程讓honk的定義具有一些彈性,例如:
1) 在runtime改變prototype函數的行為
var Car = function() {};
Car.prototype.honk = function() {
console.log('honk honk');
};
var myCar = new Car();
myCar.honk(); // executes Car.prototype.honk() and outputs "honk honk"
Car.prototype.honk = function() {
console.log('meep meep');
};
myCar.honk(); // executes Car.prototype.honk() and outputs "meep meep"
2) 在runtime新增prototype函數
var Car = function() {};
Car.prototype.honk = function() {
console.log('honk honk');
};
var myCar = new Car();
Car.prototype.drive = function() {
console.log('vrooom...');
};
myCar.drive(); // executes Car.prototype.drive() and outputs "vrooom..."
3) 物件可以個別自訂函數的行為 (意義上類似Java Override)
var Car = function() {};
Car.prototype.honk = function() {
console.log('honk honk');
};
var myCar1 = new Car();
var myCar2 = new Car();
myCar1.honk(); // executes Car.prototype.honk() and outputs "honk honk"
myCar2.honk(); // executes Car.prototype.honk() and outputs "honk honk"
myCar2.honk = function() {
console.log('meep meep');
};
myCar1.honk(); // executes Car.prototype.honk() and outputs "honk honk"
myCar2.honk(); // executes myCar2.honk() and outputs "meep meep"
prototype其實是非常有趣的一種用法,透過一連串的prototype指定,Javascript還可以實現Java中的inheritance概念。
假設我們說Car跟Bike都是一種交通工具(Vehicle),Vehicle共同的行為就是可以駕駛(drive),不過Car有喇叭可按(honk),但Bike是按鈴(ring)。
在Javascript中可以使用prototype來描述這兩種交通工具:
var Vehicle = function() {};
Vehicle.prototype.drive = function() {
console.log('vrooom...');
};
var Car = function() {};
var Bike = function() {};
Car.prototype = new Vehicle();
Bike.prototype = new Vehicle();
Car.prototype.honk = function() {
console.log('honk honk');
};
Bike.prototype.ring = function() {
console.log('ring ring');
};
var myCar = new Car();
var myBike = new Bike();
myCar.drive(); // outputs "vrooom..."
myBike.drive(); // outputs "vrooom..."
myCar.honk(); // outputs "honk honk"
myBike.ring(); // outputs "ring ring"
4. 使用Object.create()使得物件彼此繼承
讓我們直接從Object.create函數的定義開始介紹
Object.create = function(o) {
var F = function() {};
F.prototype = o;
return new F();
};
傳入物件 o,Object.create函數會回傳一個繼承o的constructor函數F。
回到prototype的例子,我們現在使用Object.create來描述一輛屬於交通工具的汽車:
var vehicle = {};
vehicle.drive = function () {
console.log('vrooom...');
};
var car = Object.create(vehicle);
car.honk = function() {
console.log('honk honk');
};
var myCar = Object.create(car);
myCar.honk(); // outputs "honk honk"
myCar.drive(); // outputs "vrooom..."
vehicle是一個具有drive行為的物件,我們使用Object.create產生另一個物件car,除了繼承drive行為以外,我們又賦予它新的honk行為,最後再用一次Object.create產生又能honk又能drive的myCar物件。
這個用法完整呈現了Javascript與Java的不同:Java的物件導向是建立在object-class的關係上,而Javascript則是object-object的概念。透過object-object來實踐物件導向的程式,就稱為Prototype-based programming。
留言
張貼留言