各位朋友打給後,看完前面幾個章節後,不知道各位有沒有理解呢?
如果還是似懂非懂的話,沒關係哦,今天在介紹原型鏈之前,
先來說一個小故事吧!
很久很久以前,早在六大派圍攻光明頂之前,有一位小和尚每天努力砍柴挑水,有一位高人見他骨骼驚奇,是萬中選一的練武奇才,於是就帶他上山學藝去,若干年後,小和尚學藝有成,下山行俠仗義,恰巧有一天遇到一個十惡不赦的魔頭,他施展其一身武藝,但魔頭也是極為難纏,且師門好像沒有教過破解的方法,於是小和尚情急之下,變仰天大喊,祖師爺救命,說時遲,那時快,一道白光罩頂,祖師爺降駕於小和尚身上,一套套絕世武功施展了出來,但似乎效果不彰,這時小和尚心裡著急,就催促的祖師爺使出那道從天而降的掌法來降敵,但不巧的是,祖師爺的並不會如來神掌,於是乎,祖師爺便與小和尚說,你先撐著,我也去找我的祖師爺來問問...
你可能會很疑問,哩系勒公三小,孩子,剛剛這串故事,我們已經把原型鏈講完了。
小和尚 ( object )
上山學藝 ( new function someone )
找不到破解方法 ( object 沒有某某方法 )
祖師爺附體 ( __ proto __ )
效果不彰 ( __ proto __ 沒有某某方法 )
祖師爺的祖師爺 ( 繼續往原型的原型去找)
有了原型鏈的概念,下面我們就來講點正經的吧 XDDD
我們先來定義幾個概念
物件都有一個屬性叫 __ proto __,每個物件的 __ proto __ 指向建構這個物件的函式的原型,這就保證了物件能夠使用到建構函式中定義的屬性與方法。
是不是覺得有點繞口又難懂,沒關係,現在來看看日常會怎麼用 prototype 吧!
function CreatePerson(name, gender) { // 通常建構函式字首會是大寫,這是命名規則的習慣
this.name = name;
this.gender = gender;
}
CreatePerson.prototype.showName = function() {
console.log("my name : " + this.name);
}
CreatePerson.prototype.showGender = function() {
console.log("my gender : " + this.gender);
}
var p1 = new CreatePerson("Reynold", "male");
var p2 = new CreatePerson("Cher", "female");
console.log( p1.showName === p2.showName ) // true;
上面的程式碼,我們快速地產生了兩個物件,並讓他們共用了 showName 和 showGender 方法,這達到了我們節省系統資源的目的,避免重複產生方法。
是不是不太過癮,沒關係,我們再來一個
function Obj() {
this.name = "Mark";
this.run = function() {
console.log("run");
}
}
var a = new Obj();
var b = new Obj();
var c = new Obj();
// 這時候如果要幫每個物件增加同樣屬性,一般人可能會這樣做
a.height = 15;
b.height = 15;
c.height = 15;
// 但聰明的你一定會想到
Obj.prototype.height = 15;
因為 Obj.prototype === a.__ Proto __ ,所以你新增 Obj.prototype.height 屬性等同於 a.__ Proto __.height,而當 a 物件在自己本身找不到 height 屬性,就會去 __ proto __ 底下尋找 height,若在找不到,就會在往上層的 __ proto __去尋找,一直找到 null 為止。
當然,我們也可以替系統內建的物件用原型來加方法,來達到擴充功能的目的。
String.prototype.toNumber = function() {
return parseInt(this);
};
var ten = "10";
console.log(ten.toNumber()); // 10
console.log(typeof (ten.toNumber())); number
最後補充個小知識,原型鏈找到最後會是 null
。
不知道大家看不看得懂我的小劇場 XDDDD,突然腦洞大開想用這樣的方式呈現,讀者給我一點回饋 RRR
參考資料:
Tommy - 深入 JavaScript 核心課程
每日頭條 - Javascript 原型鏈和原型繼承