JS之理解原型和原型鏈

原型與原型鏈

一.在瞭解原型以前須要提早了解的。
  • 1.工廠模式:建立一個函數,用特定的接口建立對象的細節。函數

    //如今要建立兩個包含 「name」和「age」的對象,
    let tom ={name:"Tom",age:16}
    let lily = { name : "Lily",age:18}
    ……//所示數量足夠具大 ,對象足夠大 ,會花費大量的時間。下面的工廠模式能 很好的解決這一問題
    //工廠的就是隻流水線不是全部都是要人工,節約人力成本。
      function person(name,age){
          let  obj = {}; //建立一個對象 ;
          obj.name = name ; //爲對象添加細節
          obj.age = age ;
          obg.sayHello= function (){
            alert ("Hello"+this.name)
          };
          return obj;} //返回這個對象 
      let tom = person("Tom",16);
      let lily = person("Lily",18)
    • 工廠函數的優點:避免的大量的重複代碼;
    • 工廠函數的劣勢:其建立的對象不能標誌爲一種特定的類型,沒有解決對象識別的問題,不知道對象的類型。構造函數能很好的解決這個問題。
  • 2.構造函數:自定義構造函數,能夠自定義對象類型的屬性和方法。this

    function Person(name,age){   
          this.name = name ; //爲對象添加細節
          this.age = age ;
          this.sayHello= function (){
            alert ("Hello"+this.name)
          };
      let tom = new Person("Tom",16);
      let lily =new Person("Lily",18)
    • new的過程作了三件事建立了一個對象;this指向這個對象;返回這個對象;
    • 兩個實例對象都有一個屬性constructor(構造函數),指向Person;這就是能夠經過constructor判斷對象類型的原理。
    • 存在的問題:構造函數的每一個方法都要在實例上從新建立一遍,雖然函數名是同樣的,可是不相等的。

二.原型模式
  • 1.以下,與構造函數模式不一樣的是,原型模式的每一個實例都是訪問同一屬性同一函數,,函數不用從新建立。spa

    function Person () {
       this.x = 100;
    }
    Person.prototype.name = 'Tom';
    Person.prototype.age = 18;
    Person.prototype.sayHello =  function (){
      alert(`Hello${this.name}`)
    }
    let Tom = new Person()
    Tom.sayHello()
  • 2.原型對象prototype

    • ①每一個函數數據類型(普通函數,類)上,都有一個屬性,叫prototype,是一個對象,這個函數指向函數的原型對象;
    • prototype這個對象上,自帶一個屬性,constructor指向當前這個類;
    • ③當爲實例添加屬性時,這個屬性會屏蔽原型對象中保存的同名屬性,可是事實阻止訪問,並無修改那個屬性,若將同名的實例屬性設置爲null,一樣會屏蔽,可是若用delete,則能夠刪除實例屬性,能夠從新訪問原型中的屬性。3d

      alert(Tom.age);  //18
      let Tom.age = 20;
      alert(Tom.age); //20
      delete Tom.age;
      alert(Tom.age); //18

      clipboard.png

    • ④屬性分爲兩種,來自實例(或者是構造函數)或是原型,原型上的屬性和方法都是共有的,構造函數中的屬性方法都是私有的,構造函數中的this都是實例。爲何私有屬性(來自實例的屬性)的查找等級要高呢?這就涉及到原型鏈。
  • 3.原型鏈:每一個對象數據類型(普通對象,prototype,實例)都有一個屬性,叫作__proto__code

    • 好比咱們console.log(Tom.age)的查找過程是怎樣的呢?①首先在私有空間內查找age屬性,私有空間的屬性包括自身的屬性和從類那裏繼承的屬性,
    • ②找不到的話:經過__proto__去當前實例所屬類的原型上進行查找,找到的話,說明是共有屬性;
    • ③還找不到的話:繼續經過__proto__去當前實例所屬類的原型進行查找,找不到將繼續經過__proto__一直找到Object
      clipboard.png
    • ④曲線表明Person的原型對象;曲線中,實例Tom經過__proto__指向Tom所屬類(Person)的原型(Person Prototype);曲線③中,Person的原型對象經過__proto__找到Person對象的所屬類,也就是Object(函數也是對象類,萬物皆對象),指向它的原型(ObjectPrototype) ;曲線5中,指向Obeject所屬類的原型,它的類就是它本身,因此此時不在有__proto__整個屬性查找結束,這就是原型鏈的查找過程。
      clipboard.png
    • ⑤經過hasOwnProperty來判斷屬性,這個方法就是經過④中的查找過程,在基類Object中找到的。 判斷屬性是否在對象上「name」 in Tom,其中in的查找過程也是經過上述的查找過程。對象

      function hasPrototypeProperty(object,attr){
         return !object.hasOwnProperty(attr) && (attr in object);}
  • 4.關於原型須要注意的幾點blog

    • ①使用簡單原型語法的時候,注意constructor的指向問題,繼承

      Person.prototype={  //此時constructor指向Object構造函數
         name : 'Tom',
         age:18
      }
      Person.prototype={  //此時constructor指向Person
         constructor:Person,
         name : 'Tom',
         age:18
      }
    • ②添加和修改原型的屬性和方法都能當即在全部對象實例中反應出來(即便先建立實例後修改原型);可是若是重寫整個原型對象,建立在前的實例並不能得到重寫後的屬性或方法。這是由於重寫原型以後是新生成原型對象,和聲明在前的任何已經存在的實例都沒有關係。
相關文章
相關標籤/搜索