javaScript 面向對象一

1.對象的創建(javaScript幾乎所有都是對象)

 

創建一個Object(Object是javaScript中所有對象的基類,所有的對象都繼承Object)

var bingo = new Object();

這時變量 bingo 指向一個Object的實例,你可以爲該對象動態的添加屬性和函數,如下:

 

var bingo = new Object();

bingo.say = 'hello';

bingo.do = function()

{

   alert(this.say);

}


a.javaScript對象數組

 

javaScript是把對象當作關聯數組,也可以用數組的形式來調用 屬性和方法,如下:

屬性:var theFirstName = bingo[‘say’];

方法:bingo[‘do’];

 

往一個對象添加方法時,你也可以添加 一個已經存在的方法;如下:

爲bingo對象添加一個已經存在的方法sayLoudly();

 

function sayLoudly()

{

    console.log(this.say);

    console.log(typeof this);

}

 

var bingo = new Object();

bingo.say = 'hello';

bingo.sayLoudly = sayLoudly;


 

因爲this它指向的對象會在運行時動態地計算,所以因不同對象的調用它會指向不同的對象,例如下面:

sayLoudly();

首先單單直接調用sayLoudly()的話,則相當於window.sayLoudly();此時this指向的就是window對象,

因爲這裏的window對象沒有say屬性,所以輸出undefined,因爲window對象也是Object,所以輸出Object,如下:

undefined 

object


 

bingo.sayLoudly();

接着用bingo.sayLoudly();,此時this指向的是bingo對象,因爲這裏的bingo對象已有屬性say,所以輸出hello,

又因爲bingo是一個Object的對象,則輸出Object,如下:

hello 

object 


 

  

 

b.Json形式創建對象

 

var bingo = 

{  

     say:”hello”,

     do: function()

     {

        alert(this.say); 

     },

     sayLoudly:sayLoudly,

 

    //對象裏面嵌套對象

    LastName:{

           lastName:’world’,

           sayName: function()

           {

              alert(this.lastName);

           }

    }

}


這裏的sayLoudly:sayLoudly, javaScript會將第一個sayLoudly理解爲屬性,

第二個理解爲一個已存在的對象的引用

調用形式如下:

 

bingo.LastName.sayName(); 


 

 

2.類的定義

 

在javaScript中,類就是一個函數,這個函數被當作類的 構造函數 來提供服務,如下:

 

function newClass()
{

    alert('constructor');

    this.firstName = 'frank';

    this.sayName = function()

    {

        alert(this.firstName);

    }

}


 調用如下:

 

var nc = new newClass();

nc.sayName();


 

當var nc = new newClass();        執行newClass構造函數,即會立即彈出‘construcor’;

當nc.sayName();                           執行即會立即彈出‘frank’;

 

這裏無論創建多少個newCalss的實例,它們都含有同樣的屬性和方法,

new newClass();都調用相同的構造函數, 都彈出‘construcor’;

 

但是這種方法每新建一個newClass實例都會含有 firstName屬性和 sayName()方法的一份副本,

那麼每個實例都佔用了更多的內存(原型prototype可以解決這問題,具體如下)

 

 

a.原型prototype

 

在javaScript中,所有的函數(對象)都具有prototype屬性,它引用一個對象。

雖然原型對象在初始化時是空的,但是你在其中定義的任何屬性都會被該構造函數創建的所有對象所繼承,

這也是javaScript繼承的實現原理

 

function newClass()

{

     this.firstName = 'frank';

}

 

newCalss.prototype.sayName = function()

{

     alert(this.firstName);

}

 

var nc1 = new newClass();

nc1.sayName();

 

var nc2 = new newClass();

nc2.sayName();


 

現在,無論你創建了多少個newClass實例,在內存中sayName()函數都只會有一個單獨的實例,

因爲this是在運行時動態被計算,所以當調用nc1.sayName();時,this指向的是nc1,當調用nc2.sayName(); this指向的是nc2.

 

prototype(原型)有兩個規則:

1. 使用原型可以大量減少每個對象對內存的需求量,因爲對象可以繼承許多屬性。
2. 即使屬性在對象被創建之後才被添加至原型中,對象也能夠繼承這些屬性。

 

具體如下:

 

function MyObject()

{

}

MyObject.prototype.color = "red";

var obj1 = new MyObject();

console.log(obj1.color);               //a

console.log(obj1.soundEffect);    //a

 

MyObject.prototype.color = "blue";

MyObject.prototype.soundEffect = "boOOoing";

var obj2 = new MyObject();

console.log(obj1.color);              //b

console.log(obj1.soundEffect);   //b

console.log(obj2.color);              //b

console.log(obj2.soundEffect);   //b


 

輸出如下:

 

red 
undefined 
blue 
boOOoing 
blue 
boOOoing 

 

 

首先a中輸出的obj1.color爲red,而因爲obj1.soundEffect還未定義,不存在,所以輸出爲undefined;

而b中輸出的obj1.color爲blue,是因爲在之前執行了MyObject.prototype.color = "blue";將原型中的color修改爲了

blue,所以輸出的obj1.color才變爲blue;

b中輸出的obj1.soundEffect爲boOOoing,是因爲在之前執行了MyObject.prototype.soundEffect = "boOOoing";

爲原型添加了soundEffect 屬性,所以這時輸出的obj1.soundEffect才變爲boOOoing(注意原來輸出的是undefined)

 

 

prototype的能力不是往對象上添加屬性或方法等,而是在prototype屬性上添加屬性和方法等,然後可以通過

對象 來訪問 到其prototype上的屬性或方法等,具體如下:

 

function MyObject()

{

}

MyObject.prototype.x = 1;

var obj = new MyObject();

alert("obj.x="+obj.x);


 

這裏我們沒有給obj添加屬性x,但是依然可以得到obj.x = 1;這是因爲javaScript在對象obj上找不到屬性x,

它便會到生成obj對象的構造函數MyObject的prototype屬性中去找,於是,找到x=1。

所以這裏obj.x輸出的不是obj對象上的屬性,而是通過obj對象輸出了prototype上的屬性x

 

 

而當obj對象上也存在x屬性時,obj.x先找到了obj對象的屬性x了,所以它就不去生成obj對象的構造函數MyObject的prototype屬性中去找

具體如下:

 

function MyObject()

{

}

 

MyObject.prototype.x = 1;

var obj = new MyObject();

alert("obj.x="+obj.x);    //a

obj.x = 4;

alert("obj.x="+obj.x);    //b

 


上面a輸出的obj.x還是prototype上的屬性x的值1,而b輸出的obj.x因爲執行了obj.x = 4,所以它找到了obj對象上的屬性x,所以輸出爲4.

 

想到修改prototype,不能通過對象obj來直接修改,要通過prototype來修改,具體如下:

 

 

 

function MyObject()

{

}

MyObject.prototype.x = 1;

var obj = new MyObject();

obj.x = 2;

alert(MyObject.prototype.x); //a 彈出 1 

MyObject.prototype.x = 3;

alert(obj.x);               //b  彈出2

delete obj.x;

alert(obj.x)               //c   彈出3;


 

輸出的MyObject.prototype.x值是1,儘管再者之前執行了obj.x = 2,但這並不改變MyObject.prototype.x的值,而它是爲obj這對象上添加了屬性x,並將它賦值爲2.所以b中輸出的obj.x是2,因爲它先找到了obj這對象上的屬性x,就輸出了這x的值,而最後c輸出的obj.x爲3主要是因爲在這之前執行了delete obj.x,這將刪除了obj對象上的屬性x,所以javaScript在obj對象上找不到屬性x,它就區生成obj對象的構造函數MyObject的prototype屬性中去找,找到後並輸出了MyObject.prototype.x的值3.

 

 

function MyObject1()

{

}

MyObject1.prototype.x = 1;

function MyObject2()

{

}

MyObject2.prototype = new MyObject1();

var obj = new MyObject2();

alert(obj.x);


 

輸出obj.x的值爲1;在這裏MyObject2.prototype 被賦值爲MyObject1的一個實例,所以obj.x找到的其實是

(a)MyObject2.prototype.x,而又因爲(b)MyObject2.prototype = new MyObject1();所以將(b)代入(a)

可得(a)爲 new MyObject1().x,而在new MyObject1()對象上找不到屬性x,所以它就去生成new MyObject1()

對象的構造函數的prototype上去找,找到的其實就是MyObject1.prototype.x ,所以輸出爲1.

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章