菜鳥筆記:Javascript 物件導向

GlennJong
GlennJong
Jul 26, 2017 · 9 min read

用超級英雄圖解物件導向(疑?

初入前端的菜鳥如我,看完這篇很詳細又實用的 JavaScript 物件導向介紹,希望能有更具體的舉例來理解物件導向程式設計(OOP),因此用比較生活化的敘述和圖像來簡單介紹XD

一、物件

建立一個 Javascript 物件的方式很多種,用大括號 {} 就能夠建立一個物件了,物件裡面可以放入各式各樣的屬性,屬性的值不管是字串或是方法都可以。

為了更好理解,我們把這個物件想像是一個「人」來設定:

var p = {
name: 'Peter Parker',
hello: function () {
return 'Hi, I am ' + p.name + '.'
}
}
p.hello()

簡單來說,上面這段產生了 name 屬性是 Peter Parker 的物件,除此之外,他還具有 hello() 的 function,會跟你打招呼「Hi, I am Peter Parker.」

二、用建構式建立物件

單純建立一個物件不難,但是要快速建立很多物件就要用建構式了。
建構式可以先定義物件的特徵,也就是建立物件的屬性與 function 的藍圖。

function Person(name) {
this.name = name;
this.hello = function() {
return 'Hi, I am ' + this.name + '.';
}
}

就像是先設定出「人」應該要有的屬性,只要帶入不同的屬性值,這個程式就能產生任何人。

要實例化這個建構式,創造出物件,要用 new:
1. new 是一個運算符
2. new 的運作模式:
第一步、先建立空的物件
第二步、將 this 設定為指向新物件
第三步、叫用建構式時,將引數傳入 this 指向的屬性的值
4. 建構式不需要回傳的動作,this 會自動被回傳到新物件

var p = new Person('Peter Parker')
var b = new Person('Bruce Wayne')
p
> p {name: 'Peter Parker', hello: function}
p.hello()
> 'Hi, I am Peter Parker.'
b
> b {name: 'Bruce Wayne', hello: function}
b.hello()
> 'Hi, I am Bruce Wayne.'

變數 p 設為 name 是 Peter Parker 的人,b 則設為 name 是 Bruce Wayne 的人,建構式裡面的 this.say() 也提供了這些建立出來的 Person 物件都具有 hello 的 function,因此,執行各自的 hello() 後,他們都會跟你打招呼。

function Person(name, age, gender, weight, height) {
this.name = name;
this.age = age;
this.gender = gender;
this.weight = weight;
this.height = height;
}

建構式就跟一般物件一樣,可以定義各式各樣的屬性,因此要快速建立數個多屬性物件,就可以用這樣的建構式完成,只要寫一次建構式,剩下的就只要把變數與引數帶入,就能夠大量建立物件。

可以把身為人應該有的屬性都放進去這隻建構式。

三、用 prototype 擴充

除了可以直接把 function,寫在物件屬性裡面,也可以透過 prototype 的方式擴充,這麼做的好處可以讓建構式變得更有彈性,code 更有條理,管理性也更好。

function Person(name, wear) {
this.name = name;
this.wear = wear;
this.fly = false;
}
Person.prototype.inIronSuit = function() {
this.wear = 'ironSuit';
this.fly = true;
}

可以看到 Person 的 fly 值為 false,表示「人」本來不會飛。
另外,用 prototype 擴充了一個穿鋼鐵衣的動作,穿上鋼鐵衣就可以飛啦!

var t = new Person('Tony Stark', 'Suit')
var r = new Person('James Rhodes', 'Suit')

透過上面的建構式,創造出 Tony Stark 和 James Rhodes 兩個人,可以看到他們一開始只是穿著普通的西裝。

t
> t {name: 'Tony Stark', wear: 'Suit', fly: false}
t.inIronSuit() //穿上鋼鐵衣t
> t {name: 'Tony Stark', wear: 'Iron Suit', fly: true}
// 同理,其他人也可以穿鋼鐵衣
r.inIronSuit()
r
> r {name: 'James Rhodes', wear: 'Iron Suit', fly: true}

在 inIronSuit() 執行後,觀察Tony 和 Rhodes 前後的變化,他們的 wear 屬性都被換成了 ‘Iron Suit’,並且更改了 fly 的值為 true,如此一來他們兩個都能夠在天空飛啦!

補充說明:

擴充方法 (method) 的方式有兩種:
1.this.property = function() {}
2.prototype
寫出來的效果相同,但是其實背後原理卻是不一樣的。

function A() {
this.a = function() {}
}
A.prototype.b = function() {}var x = new A()
var y = new A()

乍看之下,a() 和 b() 都是屬於 A() 的方法,但是去檢查後會發現:

x.a === y.a
> false
x.b === y.b
> true

會造成這樣差異是因為,this 的運作方式是「複製」,a 和 b 都是源自 A() 的設定被複製、創造出來的,但是創造出物件的時候 a 和 b 都是獨立的存在,所以物件 x 的 a() 是他自己獨有的,和 y 的 a() 是不一樣的東西。
prototype 做的事情是「傳址」,所以 x.b 和 y.b 所指的東西都是指 b() 這個 function。

四、傳遞 this

方法(method)並不一定只屬於特定的建構式使用時,不同的建構式也是有可能會用到相同的方法。

不論是英雄或壞蛋,他們都有各自的名言要說,所以「說」這個動作,就不需要綁在特定建構式的 prototype。

要注意的是,say 這個方法裡面的 this,不會與 Hero 和 BadGuy 的 this 相通,因此,要使用 bind 傳遞 this,直接看看下面的例子:

function Hero(name, sentence) {
this.name = name;
this.sentence = sentence;
this.say = say.bind(this);
}
function BadGuy(name, sentence) {
this.name = name;
this.sentence = sentence;
this.say = say.bind(this);
}function say() {
return this.name + ' says "' + this.sentence + '".'
}

若沒有 bind 來做傳遞,say 的 this 就只是指「say 這個 function 本身」,say() 並不知道 this.name 是誰的名字,this.sentence 是誰的句子。

var j = new BadGuy('Joker', 'Why so serious?');
var s = new BadGuy('Darth Vader', 'I am your father.');
var h = new Hero('Hulk', 'WAAAAAAAAAA');
var a = new Hero('Captian America', 'I can do this all day.')

傳遞後的 this,就能夠讓物件屬性在各程式之間轉換,這些角色們也能夠順利地說出自己的名言了!

五、透過建構式創造出超級英雄

用以上的物件導向概念,把物件添加屬性與 method 方法,讓物件更加的豐富和完整:

function Person(name) {
this.name = name;
this.say = function() {
return 'Hi! I am ' + this.name + '.'
}
}
Person.prototype.heroEvent = function() {
if (this.name == 'Peter Parker') {
this.event = spiderBite.bind(this)
return this.name + ' have some story.'
}
else if (this.name == 'Bruce Wayne') {
this.event = parentDied.bind(this)
return this.name + ' have some story.'
}
}
function spiderBite() {
this.superHero = true;
this.ability = 'Spider power';
this.heroName = 'Spider man';
this.color = 'red and blue'
return 'Now, I got a spider power!'
}
function parentDied() {
this.superHero = true;
this.rich = true;
this.ability = 'none';
this.heroName = 'Batman';
return 'I am rich.'
}

來看看這些程式發生了什麼事吧 :P

以上,是以一個初學者的程度理解的物件導向程式設計(OOP),理解其作法後,對於很多程式的閱讀和撰寫都會更順利。

若有任何建議歡迎與我交流XD

GlennJong

Written by

GlennJong

glennjong.github.io

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade