JavaScript面向對象 ~ 原型和繼承(1)

通過面試的挫折以後,繼續深刻學習~~面試

一、原型概念的提出

傳統的構造函數對象包含方法時,在構造函數建立時,就會將全部內容從新建立一次,致使數據的重複,代碼的冗餘,以下所示:

function Person(name, age) {
  this.name = name;
  this.age = age;
  this.sayHello = function () {
    console.log("Hello");
  }
}
var p1 = new Person();
var p2 = new Person();
p1.sayHello === p2.sayHello // 結果爲false,由於p1,和p2的sayHello雖結構同樣,但倒是兩個不一樣的對象

改良1:將方法提取到外面框架

function sayHello(){
  console.log("Hello");
}
function Person(name, age) {
  this.name = name;
  this.age = age;
  this.sayHello = sayHello;
}
var p1 = new Person();
var p2 = new Person();
p1.sayHello === p2.sayHello // 結果爲true,但當代碼量不斷增長,自定義的函數愈來愈多時,可能會和框架中的函數發生命名衝突,也不利於代碼的維護

改良2:將方法放到構造函數中,且避免命名衝突,原型概念出現函數

function Person(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.sayHello = function (){
   console.log("Hello");
}
var p1 = new Person();
var p2 = new Person();
p1.sayHello === p2.sayHello // 結果爲true

構造函數一旦被建立,就會有一個原型屬性,也是個對象,能夠往裏面添加成員,每一個由構造函數建立出來的對象都會默認鏈接到原型屬性上去。學習

當js引擎查找對象屬性時,會先查找對象上是否具備該屬性,若是沒有,就會去原型屬性上去查找。this

因此,什麼是原型?原型是可以實現繼承的,當構造函數被定義的時候,原型也就被建立出來,它能夠存儲屬性和方法,既是一個屬性也是一個對象。當構造函數建立的實例對象須要訪問某個方法或屬性,而這個對象又沒有該方法或屬性的時候,它會去原型上面去查找。也就是實例對象訪問原型對象的屬性或調用原型對象的方法,說的通俗一點也就是把別的對象的方法或屬性拿過來本身用,就是繼承,因此咱們也能夠說對象繼承自其原型。prototype

引入:屬性查找機制:對象在訪問屬性或方法時,首先在當前對象查找,若是該對象有該屬性或方法,則中止查找,若是沒有,則去原型中查找,若是原型沒有,則去原型的原型中查找,直到原型的頂部,若是仍是沒有,則返回undefined(屬性)或 xxx is not a function(方法)調試

二、一些相關概念

① 面向對象的相關概念

  • 類class:在js中就是構造函數
  • 實例(instance)與對象(object)
    實例是指某個構造函數建立出來的對象,咱們稱之爲xxx構造函數的實例;
  • 鍵值對與屬性和方法
    在js中,鍵值對的集合稱之爲對象
    若是數據是值,該鍵值對爲屬性prototype
    若是數據是函數,該鍵值對爲方法method
  • 父類與子類
    js中沒有class的概念,由C++引伸過來,父類又稱基類,子類又稱派生類
    js中稱爲父對象、子對象

② 原型的相關概念

  • prototype針對構造函數,稱爲「原型屬性」
  • prototype針對構造函數建立出來的對象,稱爲「原型對象」
  • 原型屬性與原型對象的關係:
    !!構造函數的原型屬性和構造函數建立出來的對象的原型對象,是一個東西
    !!構造函數的原型屬性所指向的對象,與構造函數建立出來的對象(實例對象),這是兩個不一樣的對象(快繞暈了)

三、對象繼承自其原型

構造函數建立出來的對象(實例對象)繼承構造函數的原型屬性和原型對象code

四、原型的使用

  • 利用對象的動態特性:在原來的對象上添加成員
    構造函數.prototype.xxx = ccc;
  • 直接替換:從新建立一個對象
    構造函數.prototype = {};

五、__proto__

經過 proto 容許實例對象直接訪問原型,一般用於在調試中查看原型的成員(實例對象不容許修改原型)對象

六、原型的結構

有一個默認屬性:constructor => 構造器,表示該原型是與什麼構造函數聯繫起來的
∴ 構造函數經過 prototype 的屬性訪問原型,原型能夠經過 constructor 訪問構造函數繼承

七、繼承

  • 簡單繼承:將別的對象的方法或屬性直接拿過來,加到本身身上,因而我就有了該方法或屬性。=> 簡單粗暴,層次清晰
  • 利用原型繼承:不須要添加成員,只要原型具備,我便有了。=> 提升複用性
  • 混合式繼承:將方法或屬性利用混入的方法,加到構造函數原型中,實例對象即有了指定的方法或屬性。

八、靜態成員和實例成員的概念

該概念由其餘面向對象的語言引入。

  • 靜態成員表示的是靜態方法和靜態屬性,由構造函數提供。
  • 實例成員表示的是實例方法和實例屬性,由構造函數建立的對象,也就是實例對象提供。

九、小結

  • 什麼是原型?
  • 如何使用原型?
  • 什麼是原型繼承? => 實例對象默認鏈接到原型中,能夠繼承原型的方法和屬性,也能夠本身給原型賦值
  • 如何實現? => 混合式繼承
相關文章
相關標籤/搜索