Javacript 中有一個思想:萬物皆對象,幾個基礎類型(String, Number, Boolean, Null, Undefined, Symbol),幾個引用類型(Array, Date, Function, Object, Regexp)本質上都是對象。es6
那麼對象之間如何實現關聯(也就是OO裏面的繼承)呢?js中經過prototype(原型)來實現。每一個對象都有一個__proto__指針,指向上一個原型,這就像是一個鏈表。最頂端的object的原型指向null, 表明終結。 因此,當咱們定義一個變量:瀏覽器
let name = new String('allen')
//let name = 'allen'
console.log('name:', name)
console.log('name.__proto__:', name.__proto__)
console.log('name.__proto__.__proto__:',name.__proto__.__proto__)
console.log('name.__proto__.__proto__.__proto__:', name.__proto__.__proto__.__proto__)
複製代碼
輸出:bash
name: [String: 'allen']
name.__proto__: [String: '']
name.__proto__.__proto__: {}
name.__proto__.__proto__.__proto__: null
[Finished in 0.1s]
複製代碼
咱們要實現繼承(至少看上去是繼承的樣子)有三種方法:函數
- Object.create(),
- Function.prototype={},
- class extend
看例子:ui
let dog = {
name: 'dog'
}
let mardDog = Object.create(dog)
複製代碼
這裏 mardDog
是一個新的空對象,存有一個指針__proto__
,指向的是 dog
對象, dog
對象中也有一個__proto__
,指向的是Object
,Object
中也有一個__proto__
,指向的是null
。 這就是原型鏈。利用Object.create(),咱們能夠建立多個對象,dog
對象都是他們的原型,那麼他們可不能夠改變dog裏面的屬性呢。答案是能夠 的,但不建議。代碼以下:this
mardDog.name = 'mardDog'
/*
dog ====> {name: 'dog'}
mardDog ====> {name: 'mardDog'}
*/
複製代碼
能夠看到,咱們並無能改變原型中的屬性。而下面這種方式:spa
mardDog.__proto__.name = 'xxxDog'
/*
dog ====> {name: 'xxxDog'}
mardDog ====> {name: 'mardDog'}
*/
複製代碼
咱們成功改變了上一層的屬性。 那麼,爲何咱們不推薦使用__proto__去改變原型中的共有屬性呢?由於這種方法很是慢,而且會嚴重影響進程。事實上,__proto__歷來沒有被寫進規範,可是瀏覽器廠商都實現了它。prototype
這個方法實際上是利用構造函數來實現 先看例子:指針
function dog (){
this.name = 'dog'
this.age = 1
}
let dog1 = new dog()
function mardDog (){
this.yiel = function (){
console.log(this.name)
}
}
mardDog.prototype = new dog()
let mardDog1 = new mardDog()
mardDog1.yiel()
複製代碼
輸出:code
dog
[Finished in 0.1s]
複製代碼
能夠看到,咱們成功實現了mardDog 對 dog的繼承
es6中實現了 class
這個關鍵字,雖然只是語法糖,本質上是方法二的封裝,但這種思路對熟悉OO的開發者是很友好的,而且把js中使人迷惑的原型封裝了起來,使它變得更容易開發。
例子:
class dog {
constructor () {
this.name = 'dog'
this.age = 1
}
}
class mardDog extends dog {
constructor () {
super()
}
yiel () {
console.log(this.name)
}
}
let mardDog1 = new mardDog()
mardDog1.yiel()
複製代碼
輸出:
dog
複製代碼
這樣咱們成功地實現了繼承
因爲es6 是大勢所趨,建議在工程環境中使用clas來實現對象的繼承。固然原型以及原型鏈的原理是必須掌握的。es6中還有一些方法也是十分有用。如下:
Object.getPrototypeOf(childobj) 顧名思義,該方法獲得childobj的prototype,也能夠理解爲父類。
Object.setPrototypeOf(childObj, obj)這個方法是將childObj設爲obj的繼承類。因爲前面提到過,對prototype的操做十分微妙,因此這個方法仍是能不用就不用,能夠用Object.create(obj)來代替
其餘方法參照MDN上的解釋