因緣際會之下,最近剛經歷了招募前端,為了準備面試題目,所以整理了一些關於JavaScript的 觀念,其中比較抽象的題目應該是ProtoType、Event loop、Bubbles Capture,這邊就先來介紹一下其中最抽象也比較難理解的JavaScript ProtoType。

JavaScript

JavaScript ProtoType 介紹

JavaScript沒有類的特性(class-based),跟Java不一樣,雖然說ES6 有class但它只是語法糖,每個JavaScript都具備有prototype,只是分為公開、私有差異,而JavaScript就用prototype來處理繼承(prototype-based),特性是延展性高。

// 使用解構復值作為參數  並且預設沒傳值預設給予字串 
function Family({m = 'no person',w = 'no person', c = 'no child'} = {}){
this.father = m;
this.mother = w;
this.chidren = c;
}

var data = {
m: 'John Paul',
w: 'Mary Alice',
c: 'Chris Paul'
};

// 繼承 Family
var paul = new Family(data)
// 等同於
// var paul[[Prototype]] = Family.prototype;
// Family.call(paul);
// paul 的 __proto__ 等於 Family();

console.log(paul);
// chidren: "Chris Paul"
// father: "John Paul"
// mother: "Mary Alice"

example codepen

console.log(paul) 截圖
JavaScript proto

接下來擴充一下 Family,增加一個function。

// 增加一個 hi function
Family.prototype.hi = function(){
console.log(`Family's child is ${this.chidren}. Family's father is ${this.father}`);
}

// this 指向調用時的物件 paul
paul.hi();
// I am Chris Paul. My father is John Paul

example codepen

JavaScript ProtoType 用來建立function也較不耗費記憶體,當我今天有多個的不同物件要產生,就不需要實際複製產生,而是轉向繼承核心的function使用prototype,這特色在es6 class撰寫時會滿明顯感受。

JavaScript ProtoType 繼承鍊

每個物件都有一個連著其他原型(prototype)的私有屬性(private property)物件。原型物件也有著自己的原型,於是原型物件就這樣鏈結,直到撞見 null 為止。看範例可能會比較好理解,

另外會發現到物件第一層會是 __proto__ (隱式原型),主要是瀏覽器會透過隱式原型指向該物件的prototype。

ps. __proto__稱為隱式原型) 與 prototype 顯式原型。

JavaScript protochain

簡單的範例

var Person = function () {
this.name = `chu`;
}

var Age = function () {
this.age = 18;
}

var Gender = function () {
this.gender = 'male';
}

Age.prototype = new Person();

Gender.prototype = new Age();

var ian = new Gender();
console.log(ian.name, ian.age, ian.gender); // chu 18 male
// 會先查找 ian 的 name ,找不到找該物件的原型prototype,
// 在找不到會在往上層去找 prototype.name 就會發現找到了停止向上查找
// 直到找不到 prototype ,__proto__為null時停止
// 整個流程稱之為 prototype chain

example codepen

JavaScript protochain

突然提到prototype,主要是在React開發時,時常用到ES6 class,才知道class背後處理了非常關於prototype繼承的細節。才知道prototype的概念形影不離。

例如一個簡單的class如下

class Person {
constructor(name){
this.name = name
}
hello(){
console.log(`hello,i am ${this.name}`)
}
}
class Age extends Person {
// constructor會在建立時倍呼叫
// 接受傳遞參數
constructor(name,age){
// 繼承父層 prototype.name
super(name);
this.age = age;
}
intro(){
console.log(`i am ${this.name}, and ${this.age} years old,`)
}
}

const ian = new Age(`chu`,18)
ian.intro(); // i am chu, and 18 years old,
ian.hello(); // hello,i am chu

example codepen

如果你有用過react的class xxx extends React.component,就會發現到其中super(props),就在講繼承React.component的props。es6 class就先不在這邊講述了,

以上就是prototype的簡單介紹,有錯誤或是問題歡迎留言。