今天繼續(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)
雖然這種形式,可以讓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)
所以需要再指定一下Person的原型繼承Animal的原型,
加上這句代碼Person.prototype.__proto__=Animal.prototype
但是proto屬性只在IE11以上版本
所以如果需要兼容更低版本的IE,需要換一種方式繼承原型
兼容IE更低的版本(IE9)
Person.prototype=Object.create(Animal.prototype)
能兼容到IE9
但是由于是直接賦值在Person.prototype屬性上,原有屬性被覆蓋
所以constructor屬性沒有了,如果需要這個(gè)屬性要重新賦值給它
Person.prototype.constructor=Person
還能兼容更低版本的IE(IE5.5)
Person.prototype=new Animal()
Person.prototype.constructor=Person
能兼容到IE5.5
還有其它方法也能兼容到(IE5.5)
function FakeAniaml(){}
FakeAniaml.prototype=Animal.prototype
Person.prototype=new FakeAniaml()
也能兼容到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},${問候語}`)
}
}