再講一遍好了(
參考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>
**
跟到寫一遍你就懂了
