JavaScript Mixin類別概念
Read From
傳統物件導向 - 三大核心概念
- 封裝
- 繼承
- 多型
傳統物件導向 - 封裝
-
將資料與其行為打包的動作
- 優點:可以隱藏私有資料
傳統物件導向 - 封裝
(封裝的另一層概念)
- 類別 (藍圖)
- 資料結構
-
資料:
- 應儲存的資訊
-
行為:
- 也就是方法
- 行為才是程式邏輯中在意的點
傳統物件導向 - 封裝
- 實體 (產品)
- 利用建構器製作出
- 經由 複製作業 將類別實體化為物件
傳統物件導向 - 封裝
-
範例:String
- 資料:隨意字元組合
- 行為:計算長度,附加資料,搜尋...etc
傳統物件導向 - 繼承
- 具體類別 承接於 抽象類別
- e.x. Vehicle & Car
- 同樣暗示著複製行為
- 子類別並沒有與父類別連結在一起
- 而是父類別將必要的東西複製給子類別


傳統物件導向 - 多型
- 使用同一個操作介面,以操作不同的物件實例
傳統物件導向 - 多型
class Vehicle {
engines = 1
ignition() {
output( "Turning on my engine." )
}
drive() {
ignition()
output( "Steering and moving forward!" )
}
}
class SpeedBoat inherits Vehicle {
engines = 2
ignition() {
output( "Turning on my ", engines, " engines." )
}
pilot() {
inherited:drive()
output( "Speeding through the water with ease!" )
}
}Which ignition will be called?
- 相對多型
- 絕對多型
JavaScript Mixin 類別設計
Mixin = Mixed in
將 父類別 的內容複製進(混入) 子類別中
JavaScript Mixin 類別設計
- 明確 Mixins
- 拷貝定義
- 利用明確多型呼叫
- 隱含 Mixins
- 不拷貝定義
- 只利用明確多型呼叫
JavaScript - 明確 Mixins
// vastly simplified `mixin(..)` example:
function mixin( sourceObj, targetObj ) {
for (var key in sourceObj) {
// only copy if not already present
if (!(key in targetObj)) {
targetObj[key] = sourceObj[key];
}
}
return targetObj;
}
var Vehicle = {
engines: 1,
ignition: function() {
console.log( "Turning on my engine." );
},
drive: function() {
this.ignition();
console.log( "Steering and moving forward!" );
}
};
var Car = mixin( Vehicle, {
wheels: 4,
drive: function() {
Vehicle.drive.call( this );
console.log( "Rolling on all " + this.wheels + " wheels!" );
}
} );- 拷貝定義
- 利用明確多型呼叫
JavaScript - 明確 Mixins
// "Traditional JS Class" `Vehicle`
function Vehicle() {
this.engines = 1;
}
Vehicle.prototype.ignition = function() {
console.log( "Turning on my engine." );
};
Vehicle.prototype.drive = function() {
this.ignition();
console.log( "Steering and moving forward!" );
};
// "Parasitic Class" `Car`
function Car() {
var car = new Vehicle();
car.wheels = 4;
// vehDrive = Vehicle::drive()
var vehDrive = car.drive;
car.drive = function() {
vehDrive.call( this );
console.log( "Rolling on all " + this.wheels + " wheels!" );
};
return car;
}
var myCar = new Car();
myCar.drive();
// Turning on my engine.
// Steering and moving forward!
// Rolling on all 4 wheels!寄生式繼承 (Parasitic inheritance)
JavaScript - 隱含 Mixins
var Something = {
cool: function() {
this.greeting = "Hello World";
this.count = this.count ? this.count + 1 : 1;
}
};
Something.cool();
Something.greeting; // "Hello World"
Something.count; // 1
var Another = {
cool: function() {
// implicit mixin of `Something` to `Another`
Something.cool.call( this );
}
};
Another.cool();
Another.greeting; // "Hello World"
Another.count; // 1 (not shared state with `Something`)- 不拷貝定義
- 只利用明確多型呼叫
JavaScript Mixin 類別設計
- 問題點
- 會有共用參考的問題
JavaScript Mixin 類別概念
By Chang Henry
JavaScript Mixin 類別概念
- 12