原型[prototype]:函數
爲其餘對象提供共享屬性的對象。this
每一個函數都有一個原型(prototype)屬性,這個屬性是一個指針,指向一個對象,這個對象包含特定實例共享的一些屬性和方法。spa
以例服人:prototype
這個例子說明了原型對象是共享的,而且是一個指針,而且對象的實例中也有指向prototype指向對象的指針。指針
function Animal(name) { this.name = name || "動物"; } Animal.prototype.runs = function() { console.log(this.name + ',跑起來了\n') } var dog = new Animal('小狗') dog.runs() //輸出"小狗跑起來了"
// 下面增長的方法,dog對象可使用嗎?
Animal.prototype.hi = function() {console.log('hi')} dog.hi() //輸出"hi",說明原型屬性是一個指針,指向一個共享對象,無論先添加的仍是後添加的方法都能調用
//dog做爲一個Animal實例,他的__proto__屬性和Animal.prototype指向同一個對象,因此纔可使用原型的方法。
console.dir(dog) // 查看 dog.__proto__
// dog.__proto__ & Animal.prototype
console.log(dog.__proto__ === Animal.prototype) //true,有相同的指針地址
原生構造函數的原型對象[不單函數有原型對象]code
console.dir(Object.prototype)對象
console.dir(Array.prototype)blog
console.dir(String.prototype)繼承
console.dir(Date.prototype)原型鏈
再看一個__proto__ & prototype的例子
var obj = { } obj.toString() // "[object Object]"
//obj 對象爲何有 toString 方法? //由於 obj 對象是 Object 構造函數的實例,obj 對象的原型指針指向 Object.prototype 對象。console.log(obj.__proto__ === Object.prototype )
經過原型關係圖理解:
再看一個函數的原型的例子
var obj = {name: 'jack'} function getName() { console.log(this.name) } // 問題:Animal.call 方法來自哪?
getName.call(obj) //來自Function對象
console.dir(getName) console.log(getName.__proto__ === Function.prototype) //true
console.log(Function.prototype.__proto__ === Object.prototype) //true
經過原型關係圖理解
原型繼承:
function Animal() { this.name = '動物' } Animal.prototype.runs = function() { console.log(this.name + ',跑起來了\n') return this } function Bird() { this.name = '鳥' } Bird.prototype = new Animal() //讓Bird的原型等於Animal的實例,由於new Animal中有__proto__指向Animal.prototype的指向(沿着原型鏈尋找),此處也能夠寫爲Bird.prototype = Animal.prototype Bird.prototype.fly = function() { console.log(this.name + ',飛走了\n') return this } function Crow(name) { this.name = name || '烏鴉' } Crow.prototype = new Bird() Crow.prototype.drink = function() { console.log(this.name + ',喝飽了水\n') return this } var crow = new Crow('一隻可愛的小烏鴉') crow.drink().runs().fly() console.dir(crow)
輸出結果:
原型總結:
每個構造函數都有一個和其對應的原型對象。
構造函數的 prototype 屬性和其實例對象的 「__proto__」 屬性指向同一個對象。
某構造函數的全部實例對象,共享一份原型對象。
全部的對象均可以經過 「__proto__」 屬性,最終鏈接到 Object.prototype 對象。
構造函數用 prototype 來定義原型的屬性和方法,實例對象用 「__proto__」 來查找原型的屬性和方法。
當查找一個對象的屬性或方法時,JS引擎會向上遍歷其原型鏈,直到找到給定名稱的屬性爲止。若是最終在 Object.prototype 對象仍然沒有找到此屬性或方法,則返回 undefined 值。