javascript關於物件導向的總結

來源:互聯網
上載者:User

對於javascript大家大部分時間用來做效果,但卻忽視了最基礎的東西,
當大家把javascript基本功學紮實了,我認為對以後寫出漂亮的js代碼有很大的協助,
今天就總結下我對javascript關於物件導向方面的理解
首先總結一下javascript中的"類",
第一種算是比較靈活的方式了,成為工廠定義方式

var obj=new Object;
obj.color='red';
obj.dodo=function(){...};

為什麼說它靈活,就是因為它可以在執行個體化對象後,可以對該對象增加屬性,可以完善我們的需求,
我們經常會得到執行個體化的對象比如:=var aa=document.getElementById('lover'),此時我們可以很方便的增加各種方法屬性,
aa.onclick=function(){...};aa.lover='i love you ';等,以至傳遞的時候只需要傳遞該對象;
 

<script   language= "javascript">
var obj=new Object;
obj.color='red';
obj.dodo=function(){alert('aa')};

for(aa in obj)
{
alert(aa);//color;dodo;
}
</script>

 

javascript中定義類我們平時都是按照這種方式,因為畢竟和java和c#比較接近,

function Car(scolor,snum)
{
this.color=scolor;
this.dodo=function(){alert('aa')};
}
//這叫做建構函式方式定義類
var obj=new Car('yellow',30);
for(aa in obj)
{
alert(aa);//color;dodo
}

上面不用多介紹大家是最熟悉的了,

接下來介紹原型方式:
什麼是原型,關於具體的概念大家可以查看資料,不想說太多,只想舉例子來說明,
 

<script   language= "javascript">
function Car(scolor,snum)
{
this.color=scolor;
this.dodo=function(){alert('aa')};
}
Car.prototype.getValue = function (){
return this.color;
}

Car.prototype.setValue = function (value){
this.color = value;
}
var obj=new Car('yellow',30);
obj.setValue(666);
alert(obj.getValue());//666
for(aa in obj)
{
alert(aa);//color;dodo;setValue;getValue
}
</script>

可以看到利用原型可以為對象增加屬性和方法,具體為什麼要利用原型來操作,概念性的問題可以查資料,
但是有一點需要注意的是:

<script   language= "javascript">
function Car(scolor,snum)
{
//this.cc="cc";
//this.docc=function(){alert(this.cc)}
}

Car.prototype.cc = "cccc"
Car.prototype.docc = function (){alert(this.cc)}

var obj=new Car('yellow',30);
for(aa in Car.prototype)
{
alert(aa);//cc;docc
}
alert(obj.cc);
obj.docc();
</script>

雖然同樣是給對象增加了cc屬性和docc方法,但是尋找順序是先尋找建構函式中是否有該屬性和方法,
沒有再搜尋propertype,根據

<script   language= "javascript">
function Car(scolor,snum)
{
this.cc="cc";
this.docc=function(){alert(this.cc)}
}

Car.prototype.cc = "cccc"
Car.prototype.docc = function (){alert(this.cc)}

var obj=new Car('yellow',30);
alert(obj.cc);//cc
delete obj.cc;
alert(obj.cc);//cccc

obj.docc();//cccc
delete obj.docc();
obj.docc();//cccc
</script>

可以看到首先刪除兩個屬性仍然可以輸出屬性值,並且第一個obj.docc()擷取的是原型中的cc屬性值

看下面的例子:
 

<script   language= "javascript">
function Car(scolor,snum)
{
this.cc="cc";
}

Car.prototype.cc = "cccc"
Car.prototype.docc = function (){alert(this.cc)}

var obj=new Car('yellow',30);
Car.prototype.docc();//cccc
</script>

可以直接調用原型方法,調用的是原型中的cc屬性而不是建構函式的,
如果沒有定義原型cc屬性,就會顯示undefined,在直接調用原型方法時這是需要注意的地方
再然後介紹一下javascript靜態實現方法:

<script   language= "javascript">
function Car()
{
Car.docc = function (){alert('cc')}
}

Car.docc = function (){alert('cccc')}

Car.docc();//cccc
var obj=new Car();//初始化後建構函式中的靜態方法覆蓋外邊定義的靜態方法,需要注意!
Car.docc();//cc
</script>

 

在瞭解以上基本概念以後,接下來介紹一下javascript如何?繼承,
我們知道所有的對象都是繼承objec類,而javascript中是怎樣繼承了object類呢?
其實在javascript中隱藏了

Car.prototype = new Object();
作用是什麼呢?很明顯Object中有toString()方法,
這樣

Car.paopertype.toString()=function(){...}
//是不是就顯而易見了,在執行個體化Car可以成功的引入該屬性,而Object中的所有屬性和方法都歸了Car,就這樣Car繼承了Object的所有屬性和方法。
<script   language= "javascript">
function Car(scolor,snum)
{
this.cc="cc";
}

alert(Car.toString());
</script>
上面的例子不是太貼切,我補充一個大家看看

<script   language= "javascript">

function obj()
{
this.aa='aa';
this.bb=function(){alert('==========')};
}

function Car()
{
 this.cc="cc";
}

Car.prototype = new obj();
var aa=new Car();
for(a in aa)
{
alert(a);//aa;bb;cc
}
aa.bb();
for(b in Car.prototype)
{
alert(b);//aa;bb
}
</script>
這樣大家就能明白

Car.prototype = new obj();
這句話的含義了。

接下來又引出一個重要屬性,constructor,

<script   language= "javascript">
function Car(scolor,snum)
{
this.cc="cc";
}

alert(Car.prototype.constructor);//constructor就是指向自己本身的一個屬性
</script>

再看下面

<script   language= "javascript">
function Car(scolor,snum)
{
this.cc="cc";
}

Car.prototype.cc = "cccc"
Car.prototype.docc = function (){alert(this.cc)}

alert(Car.prototype.constructor.prototype.cc);//cccc
Car.prototype.constructor.prototype.docc();//cccc
alert(Car.prototype.constructor===Car);//true
</script>

大家看結果明白了吧

還有讓大家比較頭疼的問題就是call和apply的用法,
首先給大家做個解釋,

function classA(scolor){
this.docc=function(){...}
}

function classB(){
//this.newMethod=classA;
//this.newMethod(scolor);
//delete this.newMethod();
//這三行與下面的call是一個效果,通過這個例子大家就應該明白call具體是怎樣執行的了,等同於上面三行的實現,
一句this.newMethod(scolor);函數調用,就將classA中的關於this.的方法和屬性就都歸classB,因為此時classA中的
this指標在classB內部指向的就是classB本身,所以這也是實現繼承的一種手段,
classA.call(this,scolor);
}

完整的例子:

<script   language= "javascript">
function classA(scolor){
this.cc=scolor;
this.docc=function(){alert(this.cc)}
}

function classB(){
classA.call(this,"yellow");
}

var obj=new classB();
alert(obj.cc)//yellow
obj.docc();//yellow
</script>

此時大家想原型方法能夠繼承嗎?其實就按照我上面的解釋,大家也該明白函數調用this.newMethod(scolor)只調用函數本身,就象我們平時使用函數一樣,不會牽扯到原型上去,所以

<script   language= "javascript">
function classA(scolor){
this.cc=scolor;
this.docc=function(){alert(this.cc)}
}

classA.prototype.dd = "dddd"
classA.prototype.dodd = function (){alert(this.dd)}

function classB(){
classA.call(this,"yellow");
}

var obj=new classB();
alert(obj.dd)//undefined
obj.dodd();//出錯沒有該方法
</script>

那我們怎麼辦呢?很簡單,只要仔細看了我上面的介紹,

<script   language= "javascript">
function classA(scolor){
this.cc=scolor;
this.docc=function(){alert(this.cc)}
}

classA.prototype.dd = "dddd"
classA.prototype.dodd = function (){alert(this.dd)}

function classB(){
}
classB.prototype = new classA("yellow");
var obj=new classB();

alert(obj.cc)//yellow
obj.docc();//yellow

alert(obj.dd)//dddd
obj.dodd();//dddd
</script>

我再給大家舉個合用的例子

<script   language= "javascript">
function classA(scolor){
this.cc=scolor;
this.docc=function(){alert(this.cc)}
}

classA.prototype.dd = "dddd"
classA.prototype.dodd = function (){alert(this.dd)}

function classB(){
classA.call(this,"red");//初始化red後繼承
}
classB.prototype = new classA("yellow");//初始化yellow後繼承
var obj=new classB();

alert(obj.cc)//red
obj.docc();//red

alert(obj.dd)//yellow
obj.dodd();//yellow
</script>

為什麼會是red不是yellow原因很簡單,一個是在建構函式內實現了繼承,一個是原型繼承,而我們說過建構函式在
原型之前調用,所以會出現red而不是yellow。

最後藉助風之石寫的一個例子結束此次文章:

<html>
<body>
<button id=btTest>test</button>
</body>
</html>
<script>
if(!document.all){
    HTMLElement.prototype.attachEvent=function(sType,foo){
        this.addEventListener(sType.slice(2),foo,false)
    }
}
Function.prototype.bindNode=function(oNode){
    var foo=this,iNodeItem
    //使用了全域數組__bindNodes,通過局部變數iNodeItem進行跨函數傳值,如果直接傳送oNode,也將造成閉包
    if(window.__bindNodes==null)
        __bindNodes=[]
    __bindNodes.push(oNode)
    iNodeItem=__bindNodes.length-1
    //釋放oNode
    oNode=null
    return function(e){
        foo.call(__bindNodes[iNodeItem],e||event)
             //需要注意的是調用了call本身就是一個調用了foo()函數的過程,所以上面返回的是一個函數
    }
}
abc()
function abc(){
    var bt=document.getElementById("btTest")
    bt.attachEvent("onclick",function(){
        //如果不經過bindNode處理,下面的結果將是undefined
        alert(this.tagName)
    }.bindNode(bt))
    //釋放bt
    bt=null
}
</script>
大家可以自己回味一下call的用法,不明白或者有錯誤可以在回複中指出,匆匆忙忙寫完一定會有不足之處,
請指教

本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/xiaolei1982/archive/2008/10/02/3010066.aspx

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.