走進(jìn)面向?qū)ο缶幊淌澜绲谌剑ㄔ屠^承)

今天繼續(xù)深入探索面向?qū)ο缶幊?br> 前面講到數(shù)組實(shí)例的原型是Array.prototype,函數(shù)實(shí)例的原型是Function.prototype,對(duì)象的原型則是Null(這一點(diǎn)前面沒講)
但是所有實(shí)例,都是由以構(gòu)造函數(shù)為原型實(shí)例化出來的
而構(gòu)造函數(shù),是指上就是函數(shù),函數(shù)的構(gòu)造函數(shù)就是Function
下面我們先看一個(gè)實(shí)例,了解一下構(gòu)造函數(shù)

構(gòu)造函數(shù)是怎么一回事?

var 數(shù)組 = new Array()
數(shù)組.__proto__===Array.prototype
//true
Array.__proro__===Function.prototype
//true
Array.prototype.__proto__===Object.prototype
//true
數(shù)組.__proto__.__proto__===Object.prototype
//true
var 函數(shù) = new Function()
函數(shù).__proto__===Function.prototype
//true
Function.__proto__===Function.prototype
/true
Function.prototype.__proto__===Object.prototype
//true
函數(shù).__proto__.__proto__===Object.prototype
//true
var 對(duì)象 = new Object()
對(duì)象.__proto__===Object.prototype
//true
Object.__proto__===Function.prototype
//true
Object.prototype.__proto__===null
true

上面的代碼說明,proto屬性指向prototype屬性
prototype屬性則是實(shí)例的原型
proto指向?qū)嵗脑?/p>

實(shí)戰(zhàn)一下,案例里Animal是Person的原型

function Animal(wuzhong){
    this.wuzhong = wuzhong
}
Animal.prototype.run = function(){
    console.log('I am running!')
}
function Person(name){
    Animal.call(this,'renlei')
//對(duì)Animal.wuzhong屬性傳參數(shù)
    console.log(this.wuzhong==='renlei')
    this.name = name
}
Person.prototype.sayhi = function(){
    console.log('nice to you!')
}
var llz = new Person('llz')
console.dir(llz)
image.png

雖然這種形式,可以讓Person構(gòu)造函數(shù)的實(shí)例也繼承Animal的屬性,
但是Person的原型對(duì)象的proto并沒有繼承Animal的原型對(duì)象

實(shí)例的原型能再繼承其它的原型嗎?(適合IE11以上版本)

function Animal(wuzhong){
    this.wuzhong = wuzhong
}
Animal.prototype.run = function(){
    console.log('I am running!')
}
function Person(name){
    Animal.call(this,'renlei')
    console.log(this.wuzhong==='renlei')
    this.name = name
}
Person.prototype.__proto__=Animal.prototype
Person.prototype.sayhi = function(){
    console.log('nice to you!')
}
var llz = new Person('llz')
console.dir(llz)
image.png

所以需要再指定一下Person的原型繼承Animal的原型,
加上這句代碼Person.prototype.__proto__=Animal.prototype
但是proto屬性只在IE11以上版本
所以如果需要兼容更低版本的IE,需要換一種方式繼承原型

兼容IE更低的版本(IE9)

Person.prototype=Object.create(Animal.prototype)

image.png

能兼容到IE9
但是由于是直接賦值在Person.prototype屬性上,原有屬性被覆蓋
所以constructor屬性沒有了,如果需要這個(gè)屬性要重新賦值給它

Person.prototype.constructor=Person
image.png

還能兼容更低版本的IE(IE5.5)

Person.prototype=new Animal()
Person.prototype.constructor=Person
image.png

能兼容到IE5.5

還有其它方法也能兼容到(IE5.5)

function FakeAniaml(){}
FakeAniaml.prototype=Animal.prototype
Person.prototype=new FakeAniaml()
image.png

也能兼容到IE5.5,
但不用再重新對(duì)constructor賦值

接下來了解一下,對(duì)實(shí)例的屬性取值

function Person(name){
    this.name = name
}
Person.prototype.物種 = 'animal'
Person.prototype.sayhi = function(){
    console.log(`Hi,I am ${this.name}`)
}
var llz = new Person('llz')
llz.age = 22
llz.sayhi()
console.log(llz.物種===Person.prototype.物種)
console.dir(llz)
Hi,I am llz
true
Person:{
    name:'llz'
    age:22
    prototype:{
        sayhi:function(){}
        物種:'animal'
    }
}

對(duì)實(shí)例的屬性取值,如果構(gòu)造函數(shù)上沒有,
則會(huì)在原型鏈上尋找有沒有該屬性,
有就會(huì)去原型鏈上取該屬性的值

llz.物種='plant'
console.log(llz.物種)
'animal'

由于屬性是在原型鏈上,構(gòu)造函數(shù)的原型上并沒有對(duì)應(yīng)屬性,
則不會(huì)修改該屬性的值

對(duì)實(shí)例的賦值

llz.__proto__.物種 = 'plant'

如果需要賦值,必須在其原型鏈上,
有該屬性的原型對(duì)象修改該屬性的值

如果要對(duì)原始的javascript對(duì)象的原型屬性修改,該怎么辦
比如對(duì)數(shù)值基本類型,調(diào)用自定義的函數(shù),
可以在對(duì)應(yīng)的Number復(fù)合對(duì)象的原型上的屬性增加函數(shù)

console.log(1.234.toFixed(1))
Number.prototype.twice = function(){
    return this.valueOf()*2
}
1..twice().twice()
1.2
4

上面案例證明了兩點(diǎn)
基本類型能調(diào)用對(duì)應(yīng)復(fù)合類型的屬性函數(shù)
在復(fù)合類型的原型上增加新的屬性,可以被復(fù)合類型對(duì)應(yīng)的所有的實(shí)例調(diào)用

接下來介紹用ES6的class語法,實(shí)現(xiàn)原型的基礎(chǔ)

class Animal{
    constructor(物種){
        this.物種 = 物種
    }
    introduce(){
        console.log(`I am ${this.物種}!`)
    }
}

class Person extends Animal{
    constructor(name){
        super('person')
        this.name = name
    }
    sayhi(問候語){
        console.log(`Hi,I am ${this.name},${問候語}`)
    }
}
var llz = new Person('llz')
console.dir(llz)
llz.sayhi('好久不見!最近還好嗎?')
Person
    name:"llz"
    物種:"person"
    __proto__:{
                     constructor:class Person
                     sayhi:sayhi(問候語){}
                      __proto__:{
                                         constructor:class Animal
                                         introduce:(問候語){}
                                         __proto__:{
                                                            constructor:Object
                                                            原生Object封裝的屬性
                                                             ……………………
                                         }
                      }
    }

extends是構(gòu)造函數(shù)的原型用來繼承其它構(gòu)造函數(shù),
super調(diào)用繼承的原型的構(gòu)造函數(shù)上的屬性方法

如果要在Person原型上增加屬性值

class Person extends Animal{
    constructor(name){
        super('person')
        this.name = name
    }
    get   物種(){
        return '人類'
    }
    sayhi(問候語){
        console.log(`Hi,I am ${this.name},${問候語}`)
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容