這篇文章, 讓你瞭解 JavaScript 中的原型(基礎篇-圖文)

JavaScript - Prototype

JavaScript是一門動態語言, 你能夠在任什麼時候候向對象上添加屬性,以下瀏覽器

function Student() {
        this.name = 'LeBron James';
        this.gender = 'Male';
    }

    var studObj1 = new Student();
    studObj1.age = 15;
    alert(studObj1.age); // 15

    var studObj2 = new Student();
    alert(studObj2.age); // undefined

正如上面的實例, age 屬性附加在 studObj1 實例上. 然而 studObj2 實例沒有這個屬性, 由於 age 屬性只在 studObj1 實例上定義了.函數

那麼, 若是想在後期添加一個屬性且能被全部的實例所共享, 該怎麼辦? 答案這就今天主角 Prototype.工具

Prototype 是一個對象, 默認狀況下與JavaScript中的任何一個函數或對象有關, 只是惟一區別在於函數的prototype 屬性是可訪問可修改的,而對象prototype屬性是不可見的.this

默認狀況下任何一個函數包含 Prototype 對象, 以下圖:spa

圖片描述
prototype 對象是一種特殊類型的可枚舉對象, 能夠將須要附加屬添加到其上,這些屬性將在其構造函數的全部實例之間共享。prototype

所以, 把上面的示例中使用函數的 prototype 來添加屬性,以便於全部對象中均可以訪問到, 以下:3d

function Student() {
        this.name = 'LeBron James';
        this.gender = 'M';
    }

    Student.prototype.age = 15;

    var studObj1 = new Student();
    alert(studObj1.age); // 15

    var studObj2 = new Student();
    alert(studObj2.age); // 15

使用 字面量 或 經過 new關鍵字和構造函數 的方式建立的每個對象都包含 __proto__ 屬性, 該屬性指向建立此對象的函數的 原型對象.調試

圖片描述

你能夠在谷歌和火狐開發者調試工具中查看該屬性(__proto__) , 根據下面的示例:code

function Student() {
        this.name = 'LeBron James';
        this.gender = 'M';
    }

    var studObj = new Student();

    console.log(Student.prototype); // object
    console.log(studObj.prototype); // undefined
    console.log(studObj.__proto__); // object

    console.log(typeof Student.prototype); // object
    console.log(typeof studObj.__proto__); // object

    console.log(Student.prototype === studObj.__proto__ ); // true

正如上面例子看到, 函數經過 [[函數名稱]].prototype 方式訪問到原型對象. 可是, 對象(實例)並無暴露出 prototype 屬性,而是使用 __proto__ 來訪問它.對象

Object 對象的原型

前面說起到, 原型對象在對象中是不可見. 使用 Object.getPrototypeOf(obj) 方法來訪問實例的原型對象. (這也是推薦方式, __proto__ 並非標準屬性, 在IE11如下其它瀏覽器中沒有實現).

function Student() {
        this.name = 'LeBron James';
        this.gender = 'M';
    }

    var studObj = new Student();

    Student.prototype.sayHi= function(){
        alert("Hi");
    };

    var studObj1 = new Student();
    var proto = Object.getPrototypeOf(studObj1);  
    // returns Student's prototype object
                
    alert(proto.constructor); 
    // returns Student function

Object 原型對象包含以下 屬性方法

屬性 描述
constructor 返回建立該實例的構造函數
__proto__ 指向建立該實例的構造函數的原型對象.
方法 描述
hasOwnProperty() 返回一個布爾值,指示對象是否包含指定的屬性做爲該對象的直接屬性,而不是經過原型鏈繼承。
isPrototypeOf() 返回一個布爾值,指示指定的對象是否位於調用此方法的對象的原型鏈中。
propertyIsEnumerable() 返回一個布爾值,該布爾值指示指定的屬性是否可枚舉。
toLocaleString() 返回本地格式的字符串.
toString() 返回對象字符串形式.
valueOf() 返回指定對象的原始值.

Chrome 和 Firfox 將對象的原型表示爲 __proto__, 而內部引用爲 [[Prototype]]. IE不支持,只有IE11包含它.

修改原型

如上所述, 每一個對象都能連接到函數的原型對象. 若是您更改了函數的原型, 則只有新對象將連接到更改後的原型. 全部其餘現有對象仍然連接到舊的函數原型. 下面實例來演示這個場景:

function Student() {
        this.name = 'LeBron James';
        this.gender = 'M';
    }

    Student.prototype.age = 15;

    var studObj1 = new Student();
    alert('studObj1.age = ' + studObj1.age); // 15

    var studObj2 = new Student();
    alert('studObj2.age = ' + studObj2.age); // 15

    Student.prototype = { age : 20 };

    var studObj3 = new Student();
    alert('studObj3.age = ' + studObj3.age); // 20

    alert('studObj1.age = ' + studObj1.age); // 15
    alert('studObj2.age = ' + studObj2.age); // 15

使用原型

原型對象被JavaScript引擎用來作兩件事:

  • 查找對象的屬性和方法
  • 在JavaScript中實現繼承
function Student() {
        this.name = 'LeBron James';
        this.gender = 'M';
    }

    Student.prototype.sayHi = function(){
        alert("Hi");
    };

    var studObj = new Student();
    studObj.toString();

在上面的示例, toString() 方法在 Student 中沒有定義, 那麼它是如何以及從哪裏找到 toString() 的呢?

在這裏,原型出現了. 首先, JavaScript 引擎檢查 studObj 是否存在 toString 方法?. 若是沒有找到,那麼它使用 studObj__proto__ 連接指向 Student函數原型對象. 若是它仍然沒法找到它那麼它會在往上層並檢查 Object 函數的原型對象,由於全部對象都是從 JavaScript 中的 Object 派生的,並查找 toString() 方法. 所以, 它在Object函數的原型對象中找到 toString() 方法,所以咱們能夠調用 studObj.toString().

查找方式,以下圖所示

圖片描述

上述就是原型基本知識點以及應用.

相關文章
相關標籤/搜索