javascript原型詳解(轉載)

一、原型
原型是 JavaScript 面向對象特性中重要的概念,在絕大多數的面嚮對象語言中,對象是基於類的(例如 Java 和 C++ ),對象是類實例化的結果。而在JavaScript 語言中,沒有類的概念①,對象由對象實例化。打個比方來說,基於類的語言中類就像一個模具,對象由這個模具澆注產生,而基於原型的語言中,原型就好像是一件藝術品的原件,我們通過一臺 100% 精確的機器把這個原件複製出很多份。

通過原型構造對象:

function Person() {}
Person.prototype.name = 'BYVoid';
Person.prototype.showName = function () {
    console.log(this.name);
};
var person = new Person();
person.showName();


上面這段代碼使用了原型而不是構造函數初始化對象。這樣做與直接在構造函數內定義屬性有什麼不同呢?

  • 構造函數內定義的屬性繼承方式與原型不同,子對象需要顯式調用父對象才能繼承構造函數內定義的屬性。
  • 構造函數內定義的任何屬性,包括函數在內都會被重複創建,同一個構造函數產生的兩個對象不共享實例。
  • 構造函數內定義的函數有運行時閉包的開銷,因爲構造函數內的局部變量對其中定義的函數來說也是可見的。

下面這端代碼能夠驗證以上問題:

function Foo() {
    var innerVar = 'hello';
    this.prop1 = 'BYVoid';
    this.func1 = function(){
        innerVar = '';
    };
}
Foo.prototype.prop2 = 'Carbo';
Foo.prototype.func2 = function () {
    console.log(this.prop2);
};
var foo1 = new Foo();
var foo2 = new Foo();
console.log(foo1.func1 == foo2.func1); // 輸出 false
console.log(foo1.func2 == foo2.func2); // 輸出 true

儘管如此,並不是說在構造函數內創建屬性不好,而是兩者各有適合的範圍。那麼我們什麼時候使用原型,什麼時候使用構造函數內定義來創建屬性呢?

除非必須用構造函數閉包,否則儘量用原型定義成員函數,因爲這樣可以減少開銷。
儘量在構造函數內定義一般成員,尤其是對象或數組,因爲用原型定義的成員是多個實例共享的。


二、原型鏈

JavaScript 中有兩個特殊的對象, Object 與 Function,它們都是構造函數,用於生成對象。Object.prototype 是所有對象的祖先, Function.prototype 是所有函數的原型,包括構造函數。
我把 JavaScript 中的對象分爲三類,一類是用戶創建的對象,一類是構造函數對象,一類是原型對象

  • 用戶創建的對象,即一般意義上用 new 語句顯式構造的對象。
  • 構造函數對象指的是普通的構造函數,即通過 new 調用生成普通對象的函數。
  • 原型對象特指構造函數 prototype 屬性指向的對象。這三類對象中每一類都有一個__proto__ 屬性,它指向該對象的原型,從任何對象沿着它開始遍歷都可以追溯到 Object.prototype。
  • 構造函數對象有prototype 屬性,指向一個原型對象,通過該構造函數創建對象時,被創建對象的 proto 屬性將會指向構造函數的 prototype 屬性。
  • 原型對象constructor屬性,指向它對應的構造函數。

讓我們通過下面這個例子來理解原型:

function Foo() {
    var innerVar = 'hello';
    this.prop1 = 'BYVoid';
    this.func1 = function(){
        innerVar = '';
    };
}
Foo.prototype.prop2 = 'Carbo';
Foo.prototype.func2 = function () {
    console.log(this.prop2);
};
var foo1 = new Foo();
var foo2 = new Foo();
console.log(foo1.func1 == foo2.func1); // 輸出 false
console.log(foo1.func2 == foo2.func2); // 輸出 true

在 JavaScript 中,繼承是依靠一套叫做原型鏈(prototype chain)的機制實現的。屬性繼承的本質就是一個對象可以訪問到它的原型鏈上任何一個原型對象的屬性。

轉自:
https://www.cnblogs.com/chihaiping/p/6373651.html

參考:
https://www.cnblogs.com/hongqin/p/5998594.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章