js面向對象詳解

最近比較忙,沒怎麼更,春困夏乏呀,天太熱了。有點不想寫代碼了,哈哈,就來寫博客了哦0..0,今天講講那些面向對象的事吧。
一般js有兩種開發模式,函數式(又叫過程化,小夥伴們平常用的最多的就是這種模式)和麪向對象(oop)(一般多用於插件開發)。
面向對象就是基於對象概念,以對象爲中心,以類和繼承爲構造機制,來認識、理解、刻畫客觀世界和設計、構建相應的軟件系統
1.爲啥要用面向對象編程?先看例子!
一般創建一個對象方法
var person=new Object()
person.name=”xiaoli” //添加一個name屬性並賦值
person.age=”18” //添加一個age屬性並賦值
person.run=function(){ //添加一個run()方法
alert(this.name+’can run’)
}
調用:person.run() //輸出:xiaoli can run

那麼問題了來了,我想創建很多類似person的對象,他們都有各自的名字和年齡,並且有run方法,我難道要一個一個的創建?哦,面向對象來!面向對象自告奮勇!我可以!好好,來你上!我能解決這種重複問題!
面向對象有好幾種方法,我們先從最開始低級的工廠模式開始!
工廠模式
function creatPerson(name.age){
var ojb=new Object()
ojb.name=name
ojb.age=age
ojb.run=function(){
alert(this.name+’can run’)
}
return ojb

}
var person1=creatPerson(‘xiaoli’,’18’)
person1.run() //輸出:xiaoli can run
大家仔細看這個模式好像就是,寫一個creatPerson函數功能就是創建對象,你每創建一個對象調用一次這個函數!工廠模式是解決了我們重複實例化的問題,但是創建不同對象我們都要重複調用這個函數,內存消耗很大,況且函數體識別也是問題!this指向不明確!

`構造函數模式:
底下這個函數稱爲構造函數,其實和普通函數是一樣的,普通函數new一下就會把他內部的this指向新的對象
function creatPerson (name,age){
this.name=name
this.age=age
this.run=function(){
alert(this.name+”can run”)
}
}
var person1=new creatPerson(‘xiali’“18”)//new 操作符實例化對象,其實就是把this指向改到新的對象上,把this指向了person1對象
調用:person1.run()//輸出 :xiaoli can run
var person2=new creatPerson(‘xiaowang’,’20’) //實例化
調用:person2.run() //輸出:xiaowang can run
哈哈,這樣同樣就解決了重複去創建多個對象的問題了,我想創建多少個,我直接new一下,然後給參數賦值,我就可以擁有類似的他們的方法和屬性哦!而且this指向很明確
那麼問題又來了!這個方法也沒有解決重複執行構造函數內部代碼的問題,內存消耗問題!爲了解決這個問題!我們又想出了新辦法!
原型
我們創建的每個函數(注意只有函數有這個屬性,實例化的對象沒有)它都有一個prototype屬性,這個屬性指向的是自己的原型對象,看例子吧!
function a(name){
this.name=name
this.run=function(){
alert(this.name+’can run’)
}
}
a.prototype是這個函數的原型對象,a函數就被稱爲他原型對象的子類型,a函數可以繼承他原型對象的所有的屬性和方法
a1=new a(‘呵呵1’)
既然每次實例化一個對象的時候我們都要重複執行構造函數裏的代碼,爲什麼我們不把經常不改變的方法直接添加到他的原型上呢?添加到原型上我們就不用每次實例化的時候就不會重複執行一些方法和屬性了的代碼了,這樣內存消耗就小了很多
看代碼!我們可以這樣
function a(name){
this.name=name //把經常改變的屬性和寫到構造函數裏
}
a.prototype.run=function(){
alert(this.name+’can run’)
}
var a1=new a(‘小李’)
a1.run() //輸出:小李can run 因爲new的時候只執行構造函數裏的代碼,同時子類型繼承原型的所有方法和屬性,這樣解決了內存消耗的問題
所以實際中我們更多是用構造函數和原型繼承一起去實現面向對象的!

最後說下apply和call是個啥玩意,其實這兩個方法都是函數體的父級原型的方法,函數體只是繼承了而已,

function add(a,b){
  alert(a+b)
} //每個函數體方法都有個原型父級,add.prototype對象,這個對象不本身就有apply和call方法,還有arguments(代表的是函數參數的數組)。所以子級可以直接調用
function getAdd(a,b){
  add.call(this,a,b) //call第一個參數是上下文執行環境的對象window,也可以用this,後面的參數就是依次爲改函數的本身參數
}
get(1,1) //輸出2

function getAdd(a,b){
  add.apply(this,arguments) //call第一個參數是上下文執行環境的對象window,也可以用this,後面的參數是一個arguments代表的就是改函數體的參數數組
}
get(1,1) //輸出2

總結:apply和call方法功能一樣,僅僅是用的時候一個必須所有參數元素,一個是參數的arguments,其實這真的沒啥可比性這兩個,因爲就是本身兩個不同的方法而已,每個方法都有自己的使用規則,恰巧他們實現了相同的功能
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章