因緣際會之下,最近剛經歷了招募前端,為了準備面試題目,所以整理了一些關於 JavaScript 的 觀念,其中比較抽象的題目應該是 ProtoType、Event loop、Bubbles Capture,這邊就先來介紹一下其中最抽象也比較難理解的 JavaScript ProtoType。
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"
console.log(paul) 截圖
接下來擴充一下 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
JavaScript ProtoType 用來建立 function 也較不耗費記憶體,當我今天有多個的不同物件要產生,就不需要實際複製產生,而是轉向繼承核心的 function 使用 prototype,這特色在 es6 class 撰寫時會滿明顯感受。
JavaScript ProtoType 繼承鍊
每個物件都有一個連著其他原型(prototype)的私有屬性(private property)物件。原型物件也有著自己的原型,於是原型物件就這樣鏈結,直到撞見 null 為止。看範例可能會比較好理解,
另外會發現到物件第一層會是 __proto__
(隱式原型),主要是瀏覽器會透過隱式原型指向該物件的 prototype。
ps. __proto__
稱為隱式原型) 與 prototype 顯式原型。
簡單的範例
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
突然提到 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
如果你有用過 react 的 class xxx extends React.component,就會發現到其中 super(props),就在講繼承 React.component 的 props。es6 class 就先不在這邊講述了,
以上就是 prototype 的簡單介紹,有錯誤或是問題歡迎留言。