Javascript之深入淺出prototype


  我們先來講一個故事,一個大大的池塘,里面有很多魚。這是屬於我們大家的池塘所以里面的魚我們都可以吃,但是我們也會從集市買一些魚放在家里,那么放在家里的魚肯定是屬於我們私人的,外人是不會擁有的。那么在js里我們就把這個池塘稱為原型對象,池塘里面我們所共享的魚稱為原型中的屬性及方法,而我們自己的魚稱為構造函數中的屬性及方法,我們是什么呢?對了,我們是對象的實例。 

  以上是為了讓大家能夠趣味性的對prototype有一個概念,接下來就通過代碼具體總結一下prototype~

一、理解prototype

  我們創建的每一個函數都有一個prototype屬性,這個屬性是一個指向對象的指針。

  構建對象中有一種模式叫做原型模式,意思是將對象實例所不可共享的屬性及方法定義在構造函數中,而將可共享的屬性及方法放在原型對象中,也就是prototype指向的對象中。以下是用原型模式創建的一個對象:

 1 function person(name, age) {  2   this.name = name;  3   this.age = age;  4 }  5 person.prototype = {  6   sayName: function() {  7     console.log(this.name);  8  }  9 }; 10 
11 var p1 = new person("Wind", 20); 12 p1.sayName(); // "Wind"
13 
14 var p2 = new person("Nic", 20); 15 p2.sayName(); // Nic

  這里我將name、age屬性定義在構造函數中,將sayName方法定義在原型中。所以p1和p2對象實例的內存空間里面各有一份name和age,但是它們卻共享一份sayName方法,意思是它們調用的sayName方法是同一個。

  試想如果我們不用prototype,而是直接將sayName寫進構造函數呢?

  那么p1和p2中將各有一份sayName,這樣浪費內存空間,所以用prototype的好處之一:提高了代碼的復用性,減少內存。

  在了解原型對象的同時我們還有一個小知識要明白:每當代碼讀取一個對象屬性的時候會執行一次搜索,搜索目標是給定名字的屬性,搜索路徑為:

    對象實例本身---->原型對象---->對象所繼承的父類對象---->父類對象原型...---->原型鏈末端

 

二、prototype的注意點

1、不可變性:盡管prototype是共享的,但不能通過對象實例重寫原型中的值,但是可以由對象統一改。通俗一點:只能爸爸統一改,不能兒子改。(這也和類型有關系,孩子不能改變基本類型的值,但是可以改變對象,比如數組)

基本類型:

 1 function person() {}  5 person.prototype = { 
 6    num: 0
 7 };  8 var p1 = new person();  9 var p2 = new person(); 10 p1.num++; 11 p2.num; // 0

非基本類型:

 1 function person() {}  5 person.prototype = {  6    num: [1,2,3]  7 };  8 var p1 = new person();  9 var p2 = new person(); 10 p1.num[2] = 8; 11 p2.num; // [1, 2, 8] 改變了

 

2、同名覆蓋性:如果我們在實例中添加了一個與原型屬性同名的屬性,那么該屬性會創建到對象實例中並且會覆蓋掉原型中的相應屬性。

 1 function person(name) {
 2   this.name = name; 
 3 }
 4 person.prototype = {
 5    age: 18 
 6 };
 7 var p1 = new person("Wind");
 8 var p2 = new person("Nic");
 9 p1.age = 20;
10 p1.age; // 20
11 p2.age; // 18 

 

3、使用對象字面量創建原型方法,會切斷之前的鏈而重寫原型鏈

 1 function person(name) {
 2   this.name = name; 
 3 }
 4 person.prototype = { 
 5   sayName: function() {
 6     console.log(this.name);      
 7   }
 8 };
 9 var p1 = new person("Wind");
10 
11 person.prototype = {
12   age : 20
13 }; 
14 p1.sayName();  // Wind
15 p1.age; // undefined
16 
17 var p2 = new person("Nic");
18 p2.sayName();  // error
19 p2.age;  // 20

  因為prototype指針指向了一個新的對象,切斷了構造函數與之前的prototype舊對象的聯系,然而p1的prototype指針指向的依舊是舊對象。而新創建的實例p2指向的prototype新對象。

 

三、總結

  prototype的用法:構造函數模型用於定義實例的屬性,而原型模型用於定義方法和共享的屬性。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM