上一篇隨筆主要講了變量提高的問題,今天咱們來說講不少前端er在初期很長一段時間內都沒有徹底搞明白的原型鏈和構造函數。javascript
1,什麼是構造函數前端
那麼要講到構造函數,必需要有一個函數,因此咱們創建一個函數java
function Person(){}
ok,既然是構造函數,那麼久要有參數和返回值 函數
Person = function(name,age,force){
this.name = name; this.age = age; this.force = force; }
一個函數就出來了,接下來咱們來看一下這個Person的__proto__和prototypethis
Person.prototype //Object {constructor:function(name,age,force),__proto__:Object}
Person.__proto__ //function(){}
好的,咱們的構造函數完成了,如今咱們來經過構造函數建立一個對象spa
var mike = new Person('mike',23,'strong');
mike //Person {name: "mike", age: 23, force: "strong"}
mike.prototpe //undefined
mike.__proto__ //Object {constructor:function(name,age,force),__proto__:Object}
在上面2段代碼,咱們能夠發現不少,仔細觀看mike.__proto__和Person.prototype,是否是發現,這二者實際上是一個東西,咱們待會驗證一下,而且發現mike.prototype是undefinedprototype
alert(mike.__proto__ === Person.prototype) //true
這樣咱們大概就瞭解了,構造函數new Person()發生時候的一個過程code
建立mike對象;對象
mike.__proto__ = Person.prototype; blog
Person.call(mike,'mike',23,'strong');
2,__proto__和prototype
__proto__按照定義來說,是對象自帶的一個屬性,這個__proto__它自己又是一個對象,__proto__的屬性,能夠被mike讀取到,但不會顯示在mike對象裏,固然__proto__對象中的屬性讀取優先級要低於mike自己
而prototype呢,則是函數的一個自帶屬性,其中prototype又有兩個元素,1,constructor指向函數自己,2,__proto__同對象中的__proto__
構造函數在建立對象是最大的特色就是會把自身的prototype按值傳遞給被構造對象的__proto__,由於prototype能夠當作對象來看,因此是按引用傳遞//糾正上次的一個錯誤
暫時我知道的prototype的做用,就是在構造對象時,將自身的prototype(引用)傳遞給新函數的__proto__
3,原型鏈
這裏我能夠舉個例子
1 mike //Person {name: "mike", age: 23, force: "strong"}; 2 mike.__proto__face = 'handsome'; 3 mike //Person {name: "mike", age: 23, force: "strong"} 4 mike.face //'handsome'
mike對象中沒有face屬性,因此往mike.__proto__中找face,找到了,顯示出來,找不到的話,往mike.__proto__.__proto__中找face,如此往復,直到某一個__proto__返回null
4,屢次繼承
function One(){ this.sayOne = function(){ alert('nameOne'); } } function Two(){}; Two.prototype = new One(); Two.prototype.sayTwo = function(){ alert('nameTwo'); } var say = new Two(); say.sayOne() //‘nameOne’ say.sayTwo() //‘nameTwo’ two.prototype //one(sayOne:function(){},sayTwo:function(){})
原理很簡單 Two.prototype = new One(); 這一步獲得 Two.prototype.__proto__ = One.prototype;
say.__proto__ = Two.prototype;
因此say.__proto__.__proto__ = One.prototype;
因此say.sayTwo = say.__proto__.sayTwo = Two.prototype.sayTwo ;
One.call(Two.prototype);
say.sayOne = say.__proto__.sayTwo = Two.prototype.sayOne;
要完成屢次繼承,只要將上一層的屬性實例化到下一層的prototype便可,由於prototype是能夠做爲對象的__proto__直接使用的!