再講一遍好了(
參考https://blog.csdn.net/cc18868876837/article/details/81211729
https://blog.csdn.net/lc237423551/article/details/80010100
)
Javascript中所有的對象都是Object的實例,並繼承Object.prototype的屬性和方法,也就是說,Object.prototype是所有對象的爸爸。
首先,我們需要牢記兩點:①__proto__
和constructor
屬性是對象所獨有的;② prototype
屬性是函數所獨有的。但是由於JS中函數也是一種對象,所以函數也擁有__proto__
和constructor
屬性,這點是致使我們產生困惑的很大原因之一。
首先盜個圖先:--》
上圖很復雜,先拆分一下
第一,這里我們僅留下__proto__屬性,它是對象所獨有的,可以看到__proto__屬性都是由一個對象指向一個對象,即指向它們的原型對象(也可以理解為父對象),那么這個屬性的作用是什么呢?它的作用就是當訪問一個對象的屬性時,如果該對象內部不存在這個屬性,那么就會去它的__proto__屬性所指向的那個對象(可以理解為父對象)里找,如果父對象也不存在這個屬性,則繼續往父對象的__proto__屬性所指向的那個對象(可以理解為爺爺對象)里找,如果還沒找到,則繼續往上找….直到原型鏈頂端null(可以理解為原始人。。。),此時若還沒找到,則返回undefined(可以理解為,再往上就已經不是“人”的范疇了,找不到了,到此為止),由以上這種通過__proto__屬性來連接對象直到null的一條鏈即為我們所謂的原型鏈。
第二,接下來我們看prototype
屬性
prototype屬性,別忘了一點,就是我們前面提到要牢記的兩點中的第二點,它是函數所獨有的,它是從一個函數指向一個對象。它的含義是函數的原型對象,也就是這個函數(其實所有函數都可以作為構造函數)所創建的實例的原型對象,由此可知:f1.__proto__ === Foo.prototype,它們兩個完全一樣。那prototype屬性的作用又是什么呢?它的作用就是包含可以由特定類型的所有實例共享的屬性和方法,也就是讓該函數所實例化的對象們都可以找到公用的屬性和方法。
******************************下面的例子來一遍你就更懂了
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <script> // es5里面的類 //1.最簡單的類 // function Person(){ // this.name='張三'; // this.age=20; // } // var p=new Person(); // alert(p.name); //2、構造函數和原型鏈里面增加方法 // function Person(){ // this.name='張三'; /*屬性*/ // this.age=20; // this.run=function(){ // alert(this.name+'在運動'); // } // } // //原型鏈上面的屬性會被多個實例共享 構造函數不會 // Person.prototype.sex="男"; // Person.prototype.work=function(){ // alert(this.name+'在工作'); // } // var p=new Person(); // // alert(p.name); // // p.run(); // p.work(); //3類里面的靜態方法 // function Person(){ // this.name='張三'; /*屬性*/ // this.age=20; // this.run=function(){ /*實例方法*/ // alert(this.name+'在運動'); // } // } // Person.getInfo=function(){ // alert('我是靜態方法'); // } // //原型鏈上面的屬性會被多個實例共享 構造函數不會 // Person.prototype.sex="男"; // Person.prototype.work=function(){ // alert(this.name+'在工作'); // } // var p=new Person(); // p.work(); // //調用靜態方法 // Person.getInfo(); // 4、es5里面的繼承 對象冒充實現繼承 // function Person(){ // this.name='張三'; /*屬性*/ // this.age=20; // this.run=function(){ /*實例方法*/ // alert(this.name+'在運動'); // } // } // Person.prototype.sex="男"; // Person.prototype.work=function(){ // alert(this.name+'在工作'); // } // //Web類 繼承Person類 原型鏈+對象冒充的組合繼承模式 // function Web(){ // Person.call(this); /*對象冒充實現繼承*/ // } // var w=new Web(); // // w.run(); //對象冒充可以繼承構造函數里面的屬性和方法 // w.work(); //對象冒充可以繼承構造函數里面的屬性和方法 但是沒法繼承原型鏈上面的屬性和方法 // 5、es5里面的繼承 原型鏈實現繼承 // function Person(){ // this.name='張三'; /*屬性*/ // this.age=20; // this.run=function(){ /*實例方法*/ // alert(this.name+'在運動'); // } // } // Person.prototype.sex="男"; // Person.prototype.work=function(){ // alert(this.name+'在工作'); // } // //Web類 繼承Person類 原型鏈+對象冒充的組合繼承模式 // function Web(){ // } // Web.prototype=new Person(); //原型鏈實現繼承 // var w=new Web(); // //原型鏈實現繼承:可以繼承構造函數里面的屬性和方法 也可以繼承原型鏈上面的屬性和方法 // //w.run(); // w.work(); // 6、 原型鏈實現繼承的 問題? // function Person(name,age){ // this.name=name; /*屬性*/ // this.age=age; // this.run=function(){ /*實例方法*/ // alert(this.name+'在運動'); // } // } // Person.prototype.sex="男"; // Person.prototype.work=function(){ // alert(this.name+'在工作'); // } // var p=new Person('李四',20); // p.run(); // function Person(name,age){ // this.name=name; /*屬性*/ // this.age=age; // this.run=function(){ /*實例方法*/ // alert(this.name+'在運動'); // } // } // Person.prototype.sex="男"; // Person.prototype.work=function(){ // alert(this.name+'在工作'); // } // function Web(name,age){ // } // Web.prototype=new Person(); // var w=new Web('趙四',20); //實例化子類的時候沒法給父類傳參 // w.run(); // // var w1=new Web('王五',22); //7.原型鏈+對象冒充的組合繼承模式 // function Person(name,age){ // this.name=name; /*屬性*/ // this.age=age; // this.run=function(){ /*實例方法*/ // alert(this.name+'在運動'); // } // } // Person.prototype.sex="男"; // Person.prototype.work=function(){ // alert(this.name+'在工作'); // } // function Web(name,age){ // Person.call(this,name,age); //對象冒充繼承 實例化子類可以給父類傳參 // } // Web.prototype=new Person(); // var w=new Web('趙四',20); //實例化子類的時候沒法給父類傳參 // // w.run(); // w.work(); // // var w1=new Web('王五',22); //8、原型鏈+對象冒充繼承的另一種方式 function Person(name,age){ this.name=name; /*屬性*/ this.age=age; this.run=function(){ /*實例方法*/ alert(this.name+'在運動'); } } Person.prototype.sex="男"; Person.prototype.work=function(){ alert(this.name+'在工作'); } function Web(name,age){ Person.call(this,name,age); //對象冒充繼承 可以繼承構造函數里面的屬性和方法、實例化子類可以給父類傳參 } Web.prototype=Person.prototype; var w=new Web('趙四',20); //實例化子類的時候沒法給父類傳參 w.run(); // w.work(); // var w1=new Web('王五',22); </script> </head> <body> </body> </html>
**
跟到寫一遍你就懂了