JavaScript原型之路
簡介
最近我在學習Frontend Masters 上的高階JavaScript系列教程,Kyle 帶來了他的“OLOO”(物件連結其他物件)概念。這讓我想起了Keith Peters 幾年前發表的一篇博文,關於學習沒有“new”的世界,其中解釋了使用原型繼承代替建構函式。兩者都是純粹的原型編碼。
標準方法(The Standard Way)
一直以來,我們學習的在 JavaScript 裡建立物件的方法都是建立一個建構函式,然後為函式的原型物件新增方法。
function Animal(name) {
this.name = name;
}
Animal.prototype.getName = function() {
return this.name;
};
對於子類的解決方案是,建立一個新的建構函式,並且設定其原型為其父類的原型。呼叫父類的建構函式,並將this設定為其上下文物件。
function Dog(name) {
Animal.call(this, name);
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.speak = function() {
return "woof";
};
var dog = new Dog("Scamp");
console.log(dog.getName() + ' says ' + dog.speak());
原型方法(The Prototypal Way)
如果你接觸過任何原型語言,你會覺得上面的例子看起來很奇怪。我嘗試過 IO 語言——一門基於原型的語言。在原型語言中,可以通過克隆物件並新增屬性和方法的方式建立一個原型。然後你能克隆剛才建立的原型,從而建立一個可以使用的例項,或者克隆它來建立另一個原型。上面的例子在 IO 裡,看起來像下面這樣:
Animal := Object clone
Animal getName := method(name)
Dog := Animal clone
Dog speak := method("woof")
dog := Dog clone
dog name := "Scamp"
writeln(dog getName(), " says ", dog speak())
好訊息(The Good News)
在JavaScript中,也可以使用這種編碼方式!Object.create 函式和 IO 裡的 clone 類似。下面是在JavaScript中,純原型的實現。除了語法不同之外,和 IO 版本一樣。
Animal = Object.create(Object);
Animal.getName = function() {
return this.name;
};
Dog = Object.create(Animal);
Dog.speak = function() {
return "woof";
};
var dog = Object.create(Dog);
dog.name = "Scamp";
console.log(dog.getName() + ' says ' + dog.speak());
壞訊息(The Bad News)
當使用建構函式時,JavaScript 引擎會進行優化。在 JSPerf 上測試兩個不同的操作,顯示基於原型的實現比使用建構函式的方式最多慢90多倍。
另外,如果你使用類似 Angular 的框架,當建立控制器和服務時,必須使用建構函式。
引入類(Enter Classes)
ES6帶來了新的 class 語法。但其只是標準建構函式方法的語法糖。新的語法看起來更像 Java 或 c#,但其幕後仍然是建立原型物件。這會讓來自基於類語言的人感到迷惑,因為當建立原型時,他們希望類和他們的語言有相同的屬性。
class Animal {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
class Dog extends Animal {
constructor(name) {
super(name);
}
speak() {
return "woof";
}
}
var dog = new Dog("Scamp");
console.log(dog.getName() + ' says ' + dog.speak());
結論(Conclusion)
如果讓我選擇,我會用純原型的風格。這更具有表現力,動態和有趣。由於虛擬機器會對建構函式方法進行優化,所有框架都會選擇建構函式方法,在產品程式碼中,我會繼續使用建構函式。一旦 ES6 變得流行,我希望使用新的類語法代替古老的建構函式方法。
注
原文:http://yanhaijing.com/javascript/2014/07/18/javascript-prototype
英文:http://jurberg.github.io/blog/2014/07/12/javascript-prototype/
相關文章
- 【2019 前端進階之路】JavaScript 原型和原型鏈及 canvas 驗證碼實踐前端JavaScript原型Canvas
- JavaScript原型與原型鏈JavaScript原型
- JavaScript 原型 與 原型鏈JavaScript原型
- JavaScript 原型及原型鏈JavaScript原型
- javascript——原型與原型鏈JavaScript原型
- JavaScript中原型與原型鏈JavaScript原型
- javascript之原型與原型鏈JavaScript原型
- JavaScript中的原型、原型鏈、原型模式JavaScript原型模式
- JavaScript 原型鏈JavaScript原型
- JavaScript prototype 原型JavaScript原型
- JavaScript原型梳理JavaScript原型
- JavaScript 物件 & 原型JavaScript物件原型
- JavaScript:原型(prototype)JavaScript原型
- 7. JavaScript 原型與原型鏈JavaScript原型
- JavaScript系列之原型與原型鏈JavaScript原型
- 再解 JavaScript 原型與原型鏈JavaScript原型
- 如何理解JavaScript的原型和原型鏈?JavaScript原型
- 徹底搞懂JavaScript原型和原型鏈JavaScript原型
- 深入JavaScript系列(六):原型與原型鏈JavaScript原型
- 詳解JavaScript原型JavaScript原型
- JavaScript prototype原型用法JavaScript原型
- JavaScript之原型鏈JavaScript原型
- JavaScript教程全套影片合集:原型及原型鏈JavaScript原型
- 【機制】JavaScript的原型、原型鏈、繼承JavaScript原型繼承
- JavaScript之物件和原型JavaScript物件原型
- 深入理解JavaScript原型JavaScript原型
- 理解 JavaScript 中的原型JavaScript原型
- 【Javascript 基礎】原型鏈JavaScript原型
- JavaScript從原型到原型鏈,細緻講解JavaScript原型
- [JavaScript]原型、原型鏈、建構函式與繼承JavaScript原型函式繼承
- 徹底搞清楚 JavaScript 的原型和原型鏈JavaScript原型
- javascript - 繼承與原型鏈JavaScript繼承原型
- JavaScript進階之原型鏈JavaScript原型
- javascript的原型和繼承JavaScript原型繼承
- javascript原型鏈及繼承JavaScript原型繼承
- 【譯】JavaScript 原型的深入指南JavaScript原型
- JavaScript —— this、閉包、原型、非同步JavaScript原型非同步
- JavaScript原型鏈汙染探討JavaScript原型
- JavaScript之原型深入詳解JavaScript原型