JavaScript原型與原型鏈

本文共 1475 字,讀完只需 6 分鐘javascript

1、概述

在 JavaScript 中,是一種面向對象的程序設計語言,可是 JS 自己是沒有 「類」 的概念,JS 是靠原型和原型鏈實現對象屬性的繼承。java

在理解原型前,須要先知道對象的構造函數是什麼,構造函數都有什麼特色?瀏覽器

1. 構造函數bash

// 構造函數 Person()
function Person(name, gender) {
    this.name = name;
    this.gender = gender;
}

var person = new Person("周杰倫", "男");

// 最後建立出來的對象實例 person
person

{
    name: "周杰倫",
    gender: "男"
}
複製代碼

以上代碼,普通函數 Person(),加上 new 關鍵字後,就構造了一個對象 person微信

因此構造函數的定義就是普通函數加上 new 關鍵字,並總會返回一個對象。閉包

2. 函數對象
同時,JS 中的對象分爲通常對象和函數對象。那什麼是通常對象,什麼又是函數對象呢?app

JavaScript 的類型分爲基本數據類型和引用數據類型,基本數據類型目前有 6 種(null, undefined, string, number, boolean, Symbol)。 其他的數據類型都統稱爲 object 數據類型,其中,包括 Array, Date, Function等,因此函數能夠稱爲函數對象。函數

let foo = function(){

}
foo.name = "bar";
foo.age = 24;
console.log(foo instanceof Function)  //true
console.log(foo.age)  // 24
複製代碼

以上代碼就說明了函數實際上是一個對象,也能夠具備屬性。post

2、原型鏈

JavaScript 中的對象,有一個特殊的 [[prototype]] 屬性, 其實就是對於其餘對象的引用(委託)。當咱們在獲取一個對象的屬性時,若是這個對象上沒有這個屬性,那麼 JS 會沿着對象的 [[prototype]]鏈 一層一層地去找,最後若是沒找到就返回 undefined;ui

這條一層一層的查找屬性的方式,就叫作原型鏈。

var o1 = {
    age: 6
}
複製代碼

那麼,爲何一個對象要引用,或者說要委託另一個對象來尋找屬性呢?

本文開篇的第一句話,就指出來的,JavaScript 中,和通常的 OOP 語言不一樣,它沒有 '類'的概念,也就沒有 '模板' 來建立對象,而是經過字面量或者構造函數的方式直接建立對象。那麼也就不存在所謂的類的複製繼承。

3、原型

那什麼又是原型呢?

既然咱們沒有類,就用其餘的方式實現類的行爲吧,看下面這句話↓↓。

1. 每一個函數都有一個原型屬性 prototype 對象

function Person() {

}

Person.prototype.name = 'JayChou';

// person1 和 person2 都是空對象
var person1 = new Person();
var person2 = new Person();

console.log(person1.name) // JayChou
console.log(person2.name) // JayChou
複製代碼

經過構造函數創造的對象,對象在尋找 name 屬性時,找到了 構造函數的 prototype 對象上。

這個構造函數的 prototype 對象,就是 原型

用示意圖來表示:

查找對象實例屬性時,會沿着原型鏈向上找,在現代瀏覽器中,標準讓每一個對象都有一個 __proto__ 屬性,指向原型對象。那麼,咱們能夠知道對象實例和函數原型對象之間的關係。

2. 每一個原型對象都有一個 constructor 屬性指向關聯的構造函數

爲了驗證這一說話,舉個例子。

function Person() {}

Person === Person.prototype.constructor; // true
複製代碼

那麼對象實例是構造函數構造而來,那麼對象實例是否是也應該有一個 constructor 呢?

function Person() {}

const person = new Person();
person.constructor === Person // true
複製代碼

但事實上,對象實例自己並無 constructor 屬性,對象實例的 constructor 屬性來自於引用了原型對象的 constructor 屬性

person.constructor === Person.prototype.constructor // true
複製代碼

3. 原型鏈頂層:Object.prototype.__proto__== null

既然 JS 經過原型鏈查找屬性,那麼鏈的頂層是什麼呢,答案就是 Object 對象,Object 對象其實也有 __proto__屬性,比較特殊的是 Object.prototype.__proto__ 指向 null, 也就是空。

Object.prototype.__proto__ === null
複製代碼

咱們回過頭來看函數對象:

全部函數對象的proto都指向Function.prototype,它是一個空函數(Empty function)

Number.__proto__ === Function.prototype  // true
Number.constructor == Function //true

Boolean.__proto__ === Function.prototype // true
Boolean.constructor == Function //true

String.__proto__ === Function.prototype  // true
String.constructor == Function //true

// 全部的構造器都來自於Function.prototype,甚至包括根構造器Object及Function自身
Object.__proto__ === Function.prototype  // true
Object.constructor == Function // true

// 全部的構造器都來自於Function.prototype,甚至包括根構造器Object及Function自身
Function.__proto__ === Function.prototype // true
Function.constructor == Function //true

Array.__proto__ === Function.prototype   // true
Array.constructor == Function //true

RegExp.__proto__ === Function.prototype  // true
RegExp.constructor == Function //true

Error.__proto__ === Function.prototype   // true
Error.constructor == Function //true

Date.__proto__ === Function.prototype    // true
Date.constructor == Function //true

複製代碼

全部的構造器都來自於 Function.prototype,甚至包括根構造器Object及Function自身。全部構造器都繼承了·Function.prototype·的屬性及方法。如length、call、apply、bind

以圖會友,這就是網上常常看到的 JS 原型和原型鏈關係圖:

對於以上看似很複雜的關係圖,只須要理解 5 點:

  1. 每一個函數都有一個原型屬性 prototype 對象
  2. 普通對象的構造函數是 Object(),因此 Person.prototype.__proto__ === Object.prototype
  3. 函數對象都來自於 Function.prototype
  4. 函數對象也是對象,全部 Function.prototype.__proto__ === Object.prototype
  5. 記住,全部函數原型的都是 Object() 的實例
  6. Object.prototype.__proto__ 是 null

總結

以上就是 JavaScript 中原型和原型鏈的知識。因爲 JS 沒有'類', 因此採用了原型的方式實現繼承,正確的說法是引用或者委託,由於對象之間的關係不是複製,而是委託。在查找屬性的時候,引用(委託)原型對象的屬性,也就是咱們常說的原型繼承。

歡迎關注我的微信訂閱號,專一分享原創文章

掘金專欄 JavaScript 系列文章

  1. JavaScript之變量及做用域
  2. JavaScript之聲明提高
  3. JavaScript之執行上下文
  4. JavaScript之變量對象
  5. JavaScript原型與原型鏈
  6. JavaScript之做用域鏈
  7. JavaScript之閉包
  8. JavaScript之this
  9. JavaScript之arguments
  10. JavaScript之按值傳遞
  11. JavaScript之例題中完全理解this
  12. JavaScript專題之模擬實現call和apply
相關文章
相關標籤/搜索