本篇大綱
- 原型是什麼
- 原型鏈是什麼
- 檢查屬性以及實例的方法
JavaScript 的物件通過原型 (Prototype) 機制來達到相互繼承功能。當使用 Constructor Function 創造 object 時,所創造出來的物件不共享 constructor 的屬性和方法。所創造出來的物件稱為實例 ( instance ).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
function Person(first, last, gender) { this.first = first; this.last = last; this.gender = 'male'; }
var person_one = new Person(); var person_two = new Person();
person_two.gender = 'female';
console.log(person_one.gender); console.log(person_two.gender);
|
person_one 和 person_two 的 gender 屬性是獨立的,因此在修改 person_two 的 gender 時,不會影響到 person_one,兩個函式之間不共享屬性。
原型 Prototype
如果要讓所有實例都共享同一個屬性,可以運用實例的特性:當函式以構建函式的形式創建的時候,所創建的物件都有一個隱含的屬性( __proto__ ),指向該構建函式的原型物件。
因此如果將屬性設置到 prototype,所有函式都能夠存取到該屬性。設置的方式為:FunctionName.prototype.variable .

Person 這個函式物件以及他的實例的 __proto__ 指向的是同一個 prototype。這裡將 gender 這個屬性設置到 prototype,因此所有實例都可以取得這個屬性。
person_one 這個實例另外設置了 gender 屬性。當呼叫物件的屬性時,首先會查找自身物件是否有該屬性,有的話就會回傳本身的,沒有的話則會往上一層 prototype 找,直到找到該屬性為止,如果到頂層都沒有找到就會回傳 undefined。因此,person_one.gender 會回傳 female , 而 person_two.gender 回傳 male .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
function Person() {}
Person.prototype.gender = 'male'; Person.prototype.sayHello = function () { return 'Hellooo'; };
var person_one = new Person(); var person_two = new Person();
person_one.gender = 'female';
console.log(person_one.gender); console.log(person_two.gender); console.log(person_one.sayHello()); console.log(person_one.age) > female > male > Hellooo > undefined;
|
小結:
- 原型物件就像是一個公共區域,同一個構造函式的實例都可以取得這個原型物件。
- 當呼叫物件的屬性時,如果物件有該屬性,就會使用自身的;沒有的話就會往 prototype 找。
- prototype 裡也可以設置 function
- 如果普通函式呼叫 prototype method,並不會起任何作用。
關於原型鏈
實例的 __proto__ 會指向 constructor 的 prototype。 如果呼叫某個物件的屬性,如 person_two.gender, 如果在自身 object 裡找不到,就會往上一層 Person.prototype 找,如果還是沒有,就找 Person.prototype.__ proto __ ,直到找到某個東西的 __proto__ 是 null 為止。
眾多 __ptoto__ 串起來的鏈就稱為原型鏈。通過原型鏈,可以達成類似繼承的功能,得以呼叫自己 parent 的 method.
PS: Person.__ proto __ 是 Function.prototype , Person 是 Function 的 instance.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function Person(first, last) { this.first = first; this.last = last; }
Person.prototype.gender = 'male'; var person_one = new Person('Sky', 'Walker');
console.log(person_one.__proto__ === Person.prototype);
console.log(Person.prototype.__proto__ === Object.prototype);
console.log(Object.prototype.__proto__);
|
其他
檢查屬性
in: 使用 in 檢查物件中是否含有某個屬性,如果物件中沒有,但 prototype 有會返回true
object.hasOwnProperty(): 檢查物件自身有沒有這個屬性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
function Person(first,last) { this.first = first this.last = last }
Person.prototype.gender = "male"
var person\_one = new Person("Sky","Walker") person\_one.age = 42
console.log("gender" in person\_one) console.log("age" in person\_one) console.log(person\_one.hasOwnProperty("gender")) console.log(person\_one.hasOwnProperty("last")) console.log(person\_one.hasOwnProperty("age"))
|
檢查實例
instanceOf: 檢查函式是不是某個 constructor 的 instance , 會往上搜查原型鏈。
1 2 3 4 5 6 7 8 9 10 11
|
function Person(first,last) { this.first = first this.last = last }
var person\_one = new Person("Sky","Walker")
console.log(person\_one instanceof Person) console.log(person\_one instanceof Object)
|
參考資料
- 該來理解 JavaScript 的原型鍊了
- 你不可不知的原型鏈 Prototype | JavaScript 鍛鍊日記