JavaScript它沒有"子類"和"父類"的概念,也沒有"類"(class)和"實例"(instance)的區分(ES6以前),全靠一種很奇特的"原型鏈"(prototype chain)模式,來實現繼承,在學習原型和原型鏈以前咱們先介紹一下'構造函數'git
構造函數其實就是普通的 函數,只不過咱們爲了一眼能看出這是一個構造函數,習慣函數名稱都要首字母大寫,調用方式有所不一樣須要用new關鍵字來調用,構造函數的目的就是爲了作一個"模具"(建立自定義類),作蛋糕要有蛋糕的模具,寫代碼也是同樣,具備相同方法和屬性的代碼用這個模具生產(new)一個就能夠了,而不須要把全部的方法和屬性在從新寫一遍github
<script>
function Animal(name, age) {//構造函數
this.name = name;//屬性
this.age = age;//屬性
this.say = function () {//方法
console.log(this.name);
}
}
var monkey = new Animal("猴子", 4);
monkey.say()//輸出猴子
var dog = new Animal("狗子", 3);
dog.say()//輸出狗子
</script>
複製代碼
結果輸出: 函數
經過以上輸出結果能夠看出,每new一個Animal()實例對象就會生成一個對應的Animal對象,對象裏除了變化的屬性(name,age),say這個方法是不會變的,那咱們想每建立一個對象就添加一個重複的方法,這樣是對資源的一種浪費,那咱們應該吧這類方法放在一個地方,讓每一個實例對象都能訪問到呢?解決這問題就須要咱們知道原型(prototype)繼續看下面文章學習
那麼原型是什麼呢? w3chool寫到:全部 JavaScript 對象都從原型繼承屬性和方法。廢話很少說,看題!!!!!ui
<script>
function Animal(name, age) {//構造函數
this.name = name;//屬性
this.age = age;//屬性
}
Animal.prototype.say = function () {//把say方法放到原型上
console.log(this.name);
}
Animal.prototype.isAnimal = true;//把isAnimal屬性放到原型上
var monkey = new Animal("猴子", 4);
console.log(monkey)
monkey.say()//輸出猴子
console.log(monkey.isAnimal)
var dog = new Animal("狗子", 3);
console.log(dog)
dog.say()//輸出狗子
console.log(dog.isAnimal)
</script>
複製代碼
結果輸出: this
咱們發現,say()方法和isAnimal屬性不在每一個new出的對象實例上,可是咱們咱們還能打印出來???spa
__proto__是什麼?? 實例dog和monkey怎麼就能訪問到這個公共區域(Animal.prototype)了呢??? 咱們接着看下面"原型鏈".net
每一個對象都有一個__proto__屬性,這個屬性是用來標識本身所繼承的原型。也能夠這麼理解在對象實例建立的時候,經過new關鍵字調用函數時,JavaScript會把實例(如:dog)和Animal.prototype創建一個聯繫,這個聯繫就就是 __ proto __ ,而且把構造函數的prototype來實現繼承構造函數prototype的全部屬性和方法,將this綁定到實例上prototype
原型對象中有一個屬性是constructor(構造函數),他很簡單,就是指向函數對象(Animal( ))code
補充上面結構圖形
// 動物
function Animal(name) {
this.name = name;
}
// 給動物添加方法
Animal.prototype.getInfo = function () {
console.log('個人名字是:' + this.name);
};
// 貓
function Cat(name, age) {
this.age = age;
Animal.call(this, name);
}
// 設置貓的原型爲動物
Cat.prototype = new Animal();
//恢復構造函數爲貓
Cat.prototype.constuctor=Cat;
// 給貓添加方法
Cat.prototype.getAge = function () {![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20190622110602172.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI3MTE4ODk1,size_16,color_FFFFFF,t_70)
console.log('個人年齡是:' + this.age);
};
// 創建貓對象
var cat = new Cat('可愛的貓咪', 19);
cat.getInfo();
cat.getAge();
//創建動物對象
var animal = new Animal('動物');
animal.getInfo();
複製代碼
咱們瞭解了繼承那我直接往下說
上面那麼個Animal( )結構圖其實就是原型鏈的一部分,在JavaScript中萬物皆對象,每一個對象之間都是有聯繫的,他們依據 __ proto __,相互聯繫着,對象之間的繼承關係,經過prototype對象指向父類的對象,這些一直到Object對象爲止,這就是原型鏈,(你要說到Object再往上指向是啥?老子有一句名言,叫作天地萬物生於有,有生於無 因此Object.prototype.proto==null)
當JavaScript引擎查找對象的屬性時,先查找對象自己是否存在該屬性,若是不存在,會在原型鏈__proto__上查找,但不會查找自身的prototype
祭出祖傳圖例