JavaScript 物件導向入門精簡篇第1/2頁

來源:互聯網
上載者:User

封裝 :javascript中建立對象的模式中,個人認為通過閉包才算的上是真正意義上的封裝 ,所以首先我們先來簡單介紹一下閉包,看下面這個例子:

複製代碼 代碼如下:<script type="text/javascript">
function myInfo(){
var name ="老魚",age =27;
var myInfo = "my name is" + name + "i am" + age +"years old";
function showInfo(){
alert(myInfo);
}
return showInfo;
}
var oldFish = myInfo();
oldFish();
</script>

是不是很眼熟呢?沒錯了,這其實就是一個簡單的閉包應用了。簡單解釋一下:上面的函數myInfo中定義的變數,在它的內嵌函數showInfo中是可訪問的(這個很好理解),但是當我們把這個內嵌函數的返回引用賦值給一個變數oldFish,這個時候函數showInfo是在myInfo函數體外被調用,但是同樣可以訪問到定義在函數體內的變數。oh yeah!

總結一下閉包的原理吧:函數是運行在定義他們的範圍中而不是調用他們的範圍中。 其實返回一個內嵌函數也是建立閉包最常用的一種方法!

如果覺得上面的解釋太抽象的話,那麼我們一起重塑上面的函數,看看這樣是否層次鮮明一些:複製代碼 代碼如下:<script type="text/javascript">
var ioldFish = function(name,age){
var name = name,age = age;
var myInfo = "my name is" + name + "i am" + age +"years old";
return{
showInfo:function(){
alert(myInfo);
}
}
}
ioldFish("老魚",27).showInfo();
</script>

上例中的編碼風格是ext yui 中比較常見的,公私分明,一目瞭然。通過閉包,我們可以很方便的把一些不希望被外部直接存取到的東西隱藏起來,你要訪問函數內定義的變數,只能通過特定的方法才可以訪問的到,直接從外部存取是訪問不到的,寫的挺累,饒了一圈終於轉回來了,封裝嘛,不就是把不希望被別人看到的東西隱藏起來嘛!哈哈……

上例如果轉換成JQ 的風格的話,應該如下例所寫,這樣的封裝模式屬於門戶大開型模式,裡面定義的變數是可以被外部存取到的(下面的例子如果你先執行個體化一個對象,然後在函數外部存取對象的name或者 age屬性都是可以讀取到的)當然這種模式下我們可以設定一些”潛規則”,讓團隊開發成員明白哪些變數是私用的,通常我們人為的在私人變數和方法前加底線”_”,標識警戒訊號!從而實現”封裝”! 複製代碼 代碼如下:<script type="text/javascript">
var ioldFish = function(name,age){
return ioldFish.func.init(name,age);
};
ioldFish.func = ioldFish.prototype ={
init:function(name,age){
this.name = name;
this.age = age;
return this;
},
showInfo:function(){
var info = "my name is" + this.name +"i am " +this.age+"years old";
alert(info);
}
};
ioldFish.func.init.prototype = ioldFish.func;
ioldFish(" 老 魚",27).showInfo();
//var oldFish = new ioldFish("老魚",27);
//alert(oldFish.name);
</script>

可能有人會問,哪種模式好呢?這個怎麼說呢?兩種方式都有優缺點,結合著用唄!總之一個原則,一定一定不能直接被外部對象訪問的東西,就用閉包封裝吧。”一定一定”四個字很深奧,不斷實踐中才能體會真諦!

繼承 :提到這個的時候,要順便再補充一句:閉包封裝中的一個缺點,不利於子類的派生,所以閉包有風險,封裝需謹慎!直觀起見,下面例子中建立對象的方式,採用”門戶大開型”模式。

在javascript中繼承 一般分為三種方式:”類式繼承”,”原型繼承”,”摻元類”。下面簡單的介紹一下三類繼承方式的原理。

A.類式繼承: 這個是現在主流架構中常用的繼承方式,看下例:

複製代碼 代碼如下:<script type="text/javascript">
var Name = function(name){
this.name = name;
};
Name.prototype.getName = function(){
alert(this.name);
};
var Fish = function(name,age){
Name.call(this,name);
this.age = age;
};
Fish.prototype = new Name();
Fish.prototype.constructor = Fish;
Fish.prototype.showInfo = function(){
alert(this.age);
}
var ioldFish = new Fish("老魚",27);
ioldFish.getName();
</script>

上述子類Fish中並沒定義getName方法,但是子類Fish的執行個體對象ioldFish依然調用到了該方法,這是因為子類Fish繼承了超類 Name中定義的getName方法。解釋一下,這裡子類Fish的prototype指到了超類的一個執行個體,在子類Fish中雖然沒有申明 getName方法,但是根據原型鏈原理,會向prototype指向的上一級對象中去尋找是否有該方法,如果沒找到該方法,會一直搜尋到最初的原型對象。這其實也就是繼承的原理了。這裡特別說明一下,Fish.prototype.constructor = Fish;這句,由於預設子類的prototype應該是指向本身的,但是之前把prototype指向到了超類的執行個體對象,所以在這裡要把它設定回來。當然這裡可以把相關代碼通過一個函數來組織起來,起到偽裝extend的作用

B.原型繼承 ,從記憶體效能上看優於類式繼承。 複製代碼 代碼如下:<script type="text/javascript">
function clone(object){
var F = function(){};
F.prototype = object;
return new F();
};
var Name = {
name:"who's name",
showInfo:function(){
alert(this.name);
}
};
var Fish = clone(Name);
//Fish.name = "老魚";
Fish.showInfo();
lt;/script>

很明顯,原型繼承核心就是這個clone函數,同樣是原型鏈的原理,不同的是它直接複製超類,這樣的話子類就繼承了超類的所有屬性和方法.特別說一下,這類繼承並不需要建立建構函式,只需要建立一個對象字變數,定義相應的屬性和方法,然後在子類中只需要通過圓點”.”符號來引用屬性和方法就可以了.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.