1. 程式人生 > >關於構造函數和原型prototype對象的理解

關於構造函數和原型prototype對象的理解

自己的 多少 命名 自動 cti 實例化 aso image 構造

構造函數

1.什麽是構造函數

構造函數,主要用於對象創建的初始化,和new運算符一起用於創建對象,一個類可以有多個構造函數,因為函數名相同,所以只能通過參數的個數和類型不同進行區分,即構造函數的重構, 如果沒有定義構造函數,那麽該類會自動生成一個空參數的構造函數。

在javascript中,對象創建有二種方式:對象字面量和使用new表達式。

對象字面量,每創建一個對象都要重新定義一次語句,不便於創建大量相同類型的對象

技術分享圖片

new表達式,配合構造函數使用,例如var person1 = new Person("wmm",30);

   new操作符調用構造函數執行了以下幾步:

   a.首先創建一個空的person1對象 ------ var person1 = {};

   b.將空對象person1的__proto__屬性(其原型)指向構造函數的prototype對象, ------ person1.__proto__ = Person.prototype;

  c.將構造函數的作用域賦值給person1對象,Person內的this指向實例化對象person1, -------- Person.call(person1);

  d.返回新對象person1。 ------ return person1

  技術分享圖片

2.構造函數和普通函數的區別

  a.函數名稱格式,構造函數一般首字母大寫,而普通函數是一般首字母小寫,使用駝峰式命名;

  b.是否需要new調用, 構造函數需要new操作符調用,普通函數不需要;

  c.this的指向,構造函數裏this指向實例化對象,普通函數中this指向調用函數的對象,沒對象調用時,默認指向window

   d.返回值,構造函數默認返回值為實例化對象,不用return返回值,而普通函數通過return語句返回值。

prototype對象

  每一個函數都有一個prototype屬性,它指向一個對象的引用,每個實例化對象會從prototype指向的對象上繼承

屬性。一旦原型對象上的屬性發生了改變,實例化對象也會隨之發生變化。

  每一個對象都會在內部初始化一個屬性(__prototype__),屬性__proto__所指向的對象是它的原型對象,即person1.__proto__ === Person.prototype。

  當我們訪問一個對象的屬性時,如果對象內部找不到該屬性,就會去實例化對象的屬性__proto__指向的對象裏面去找這個屬性,__proto__裏面有它自己的__proto__ 屬性,然後一直找下去,直到找到為止。如果直到最頂層的Object.prototype還是找不到,則返回undefined.

所有一切對象的原型頂端,都是Object.prototype,Object.prototype的原型對象為null ,null對象沒有自己的原型

function Person(name){
      this.name  =  name;
      this.eat = function(){
            console.log("food")
      }
}
Person.prototype.age = "20";
Person.prototype.height = function(){
  this.h = "160";
   console.log(this.h);
}
var person1 = new Person("吳默默"); var person2 = new Person("wumomo");

  每個實例化對象會繼承構造函數的原型對象,實例化對象的屬性__proto__指向的是原型對象,所以person1.__proto__ === person2.__proto__ === Person.prototype

  prototype對象除了自定義屬性和__proto__屬性外,還有一個constructor屬性,constructor屬性指向的是它所在的構造函數,如下圖:

  技術分享圖片

  實例化對象本身其實沒有constructor屬性,當找不到constructor屬性時,就會根據person1.__proto__ 在其原型對象上查找。所以 person1.constructor === person1.__proto__.constructor === Person.prototype.constructor === Person

  技術分享圖片

  當重新定義prototype對象時,prototype對象原有的constructor屬性會丟失,其constuctor屬性會默認為Object(Person.prototype.constructor === Object)

  技術分享圖片

構造函數和原型prototype的區別

  每創建一個實例化對象,都要調用一次構造函數,當創建多個實例化方法時,就要調用多次構造函數,這可能會導致內存溢出,性能較差,而實例化對象會繼承prototype對象上的屬性,使用原型prototype定義時,不管實例化多少個對象,都只調用一次,所以最好的解決方式是公共的方法和屬性可以放在prototype原型中,其他的放在構造函數內。

擴展:

  isPrototypeOf() ----- 用於測試一個對象是否存在於另一個對象的原型鏈上

    Person.prototype.isPrototypeOf(person1) // ture

  instanceof ----- 一個對象是否是這個特定類或者是它的子類的一個實例,形式為 object instanceOf constructor

    person1 instanceof Person // true

    person3 instanceof Person // false

  in運算符和hasOwnProperty() ------ 都是用來檢測對象中是否存在某屬性

    in運算符 :只要通過對象能訪問到屬性就返回true,否則返回false

    hasOwnProperty() : 只能檢測到對象本身的屬性,無法檢查其原型鏈中是否具有該屬性。

    技術分享圖片

關於構造函數和原型prototype對象的理解