原型是什麼?原型和原型鏈的一些心得體會
最近在複習原型,感覺有很多要重點對待的,對面向物件的理解很有幫助。遂記。
我的理解:
原型的主要作用:共享資料,節省空間!
一、為什麼要用原型?
例如:有一個建構函式 Person :
function Person(name) {
this.name = name;
this.eat= function () {
console.log("eat");
}
}
var per1 = new Person( 'zs' );
對於這個建構函式的例項物件 per1 來說,可以呼叫方法 eat 。由此看來是沒有任何問題。但由於函式也是物件,會在記憶體中單獨開闢一個空間,因此,當例項物件多的時候,就會出現記憶體空間被很多重複的函式佔用。
如:有100個 Person 的例項物件,那麼在記憶體空間裡就會有100個eat方法佔用的空間,這些方法分別指向不同的例項物件。但是他們的執行結果卻都是一樣的。這就造成了記憶體空間的浪費!
為解決這個問題,我們需要一個共享的空間,在裡面存放一些公共的方法,屬性,這就是原型。
二、什麼是原型?
1、對於建構函式Person 來說,他有一個prototype的屬性,prototype是一個物件,他叫顯式原型。
prototype是給程式設計師使用的,是標準的屬性,且只有函式有這個屬性。
在prototype中有預設的幾個屬性,如constructor構造器等
2、對於一個例項物件per1來說,他有一個__proto__的屬性,__proto__是一個物件
__proto__是給瀏覽器使用的,不是標準的屬性,且IE8不支援。
當我們在建構函式的 prototype 中新增屬性或者方法的時候,其例項物件均可以使用這些屬性或者方法且不會單獨的開闢空間。這就完成了資料的共享!
如程式碼:
function Person(name) {
this.name = name;
}
Person.prototype.eat = function () {
console.log("eat");
}
var per1 = new Person( 'zs' );
對於例項物件per1來說,他有一個屬性name,且有一個方法 eat ,由於eat方法是寫在其建構函式的原型裡面的,因此他在例項化的時候,不會單獨為eat再開一個空間,而是直接使用eat方法。
這樣如果有100個例項物件的話,大家使用的都是同一個eat方法,不會單獨為eat開闢空間,大大節省了記憶體空間。
那麼,為什麼 例項物件per1可以呼叫寫在建構函式(person) 的 prototype 中的 方法或者 屬性呢?
因為Person 建立了per1,因此,per1中的 __proto__ 指向了 Person中的prototype,所以prototype中的屬性和方法,per1都可以通過__proto__呼叫。
即使用per1.__proto__.eat();就可以呼叫了,通常情況下我們省略__proto__不寫---> 寫 per1.eat() 即可
三、原型中的this指向?
原型中的this指向 為 呼叫這個方法的例項物件。就是哪個例項物件呼叫這個方法,this就指向哪個例項物件!
四、原型的指向可以改變嗎?
原型是一個建構函式中的一個屬性,同時他也是一個物件!物件中存放的是地址,他指向一塊記憶體空間。在這個記憶體空間中存放著公共的屬性和方法。
例如:
1 function Person(name) {
2 this.name = name;
3 }
4
5 Person.prototype.eat = function () {
6 console.log("eat");
7 }
8
9 Person.prototype = {
10 sayHi : function () {
11 console.log("Hello");
12 }
13 }
我們可以看到在程式碼的第5行時,我們在建構函式的原型中添加了一個方法,而當第9行的時候,我們重新宣告一個物件,並把物件給了原型,且新的物件裡面有一個方法sayHi。
當我們再次呼叫eat的時候,會發現無法呼叫,因為eat 在以前指向的那塊記憶體空間裡面,而原型指向已經發生了改變,不再指向之前的那塊空間了,現在指向的是有sayHi的那塊記憶體空間。
因此原型的指向是可以改變的。
五、原型鏈是什麼?
在瞭解原型鏈之前。我們要知道,任何物件中都有__proto__屬性,其指向某個建構函式的prototype物件。
建構函式的prototype屬性,也是物件,因此他也有__proto__屬性。
而我們知道,例項物件的__proto__指向的是其建構函式的 prototype物件。那麼,我們是不是可以推出--->prototype物件因為有__proto__屬性,所以,他也是一個例項物件,其__proto__屬性的指向為某個建構函式的prototype物件。同樣某個建構函式的prototype物件也有__proto__屬性,他也有指向的prototype物件,因此就會形成一條原型鏈!
如圖: