當前位置:才華齋>設計>網頁設計>

javascript的面向物件技術介紹

網頁設計 閱讀(6.94K)

javascript中的物件還沒解釋清楚怎麼回事,一上來就直奔主題,類/繼承/原型/私有變數....

javascript的面向物件技術介紹

結果呢,看了大半天,有了一個大概的瞭解,細細一回味,好像什麼都沒懂...

這篇文章是參考<>第7,8,9章而寫成的,我也會盡量按照原書的結構來說明javascript的面向物件技術(物件/陣列->函式-->類/建構函式/原型).對一些我自己也拿捏不準的地方,我會附上原文的英文語句,供大家參考.

如果不做說明,則文中出現的所有英文語句(程式體除外)都是引自<>.

-------------------------------------------------

物件和陣列(Objects and Arrays)

什麼是物件?把一些"名字-屬性"的組合放在一個單元裡面,就組成了一個物件.我們可以理解為javascript中

的物件就是一些"鍵-值"對的集合(An object is a collection of named values. These named values are usually referred

to as properties of the object.--Section3.5).

"名字"只能是string型別,不能是其他型別,而屬性的型別則是任意的(數字/字串/其他物件..).可以用new Object()來建立一個空物件,也可以簡單的用"{}"來建立一個空物件,這兩者的作用是等同的.

Js程式碼

複製程式碼 程式碼如下:

var emptyObject1 = {}; //建立空物件

var emptyObject2 = new Object(); //建立空物件

var person = {"name":"sdcyst",

"age":18,

"sex":"male"}; //建立一個包含初始值的物件person

alert(); //sdcyst

alert(person["age"]); //18

從上面的例子我們也可以看到,訪問一個物件的屬性,可以簡單的用物件名加"."後加屬性的名字,也可以用"[]"操作符來獲取,此時在[]裡面的屬性名字要加引號,這是因為物件中的索引都是字串型別的.

javasript物件中屬性的個數是可變的,在建立了一個物件之後可以隨時對它賦予任何的屬性.

Js程式碼

複製程式碼 程式碼如下:

var person = {};

= "sdcyst";

person["age"] = 18;

alert( + "__" + ); //sdcyst__18

var _person = {name:"balala","age":23}; //在構建一個物件時,屬性的名字可以不用引號來標註(name),//但是仍舊是一個字串型別.在訪問的時候[]內仍舊需要引號

alert(_person["name"] + "__" + ); //balala__23

alert(_person[name]); //undefinied

通過"."操作符獲取物件的屬性,必須得知道屬性的名字.一般來說"[]"操作符獲取物件屬性的功能更強大一些,可以在[]中放入一些表示式來取屬性的值,比如可以用在迴圈控制語句中,而"."操作符則沒有這種靈活性。

Js程式碼

複製程式碼 程式碼如下:

var name = {"name1":"NAME1","name2":"NAME2","name3":"NAME3","name4":"NAME4"};

var namestring = "";

for(var props in name) { //迴圈name物件中的屬性名字

namestring += name[props];

}

alert(namestring); //NAME1NAME2NAME3NAME4

namestring = "";

for(var i=0; i<4; i++) {

namestring += name["name"+(i+1)];

}

alert(namestring); //NAME1NAME2NAME3NAME4

操作符可以刪除物件中的某個屬性,判斷某個屬性是否存在可以使用"in"操作符.

Js程式碼

複製程式碼 程式碼如下:

var name = {"name1":"NAME1","name2":"NAME2","name3":"NAME3","name4":"NAME4"};

var namestring = "";

for(var props in name) { //迴圈name物件中的屬性名字

namestring += name[props];

}

alert(namestring); //NAME1NAME2NAME3NAME4

1; //刪除name1屬性

name["name3"]; //刪除name3屬性

namestring = "";

for(var props in name) { //迴圈name物件中的屬性名字

namestring += name[props];

}

alert(namestring); //NAME2NAME4

alert("name1" in name); //false

alert("name4" in name); //true

需要注意,物件中的`屬性是沒有順序的.

物件的constructor屬性

每一個javascript物件都有一個constructor屬性.這個屬性對應了物件初始化時的建構函式(函式也是物件).

Js程式碼

複製程式碼 程式碼如下:

var date = new Date();

alert(tructor); //Date

alert(tructor == "Date"); //false

alert(tructor == Date); //true

陣列

我們已經提到過,物件是無序資料的集合,而陣列則是有序資料的集合,陣列中的資料(元素)通過索引(從0開始)來訪問,

陣列中的資料可以是任何的資料型別.陣列本身仍舊是物件,但是由於陣列的很多特性,通常情況下把陣列和物件區別

開來分別對待(Throughout this book, objects and arrays are often treated as distinct datatypes.

This is a useful and reasonable simplification; you can treat objects and arrays as separate types

for most of your JavaScript fully understand the behavior of objects and arrays,

however, you have to know the truth: an array is nothing more than an object with a thin layer of extra

functionality. You can see this with the typeof operator: applied to an array value, it returns

the string "object". --section7.5).

建立陣列可以用"[]"操作符,或者是用Array()建構函式來new一個.

複製程式碼 程式碼如下:

var array1 = []; //建立空陣列

var array2 = new Array(); //建立空陣列

array1 = [1,"s",[3,4],{"name1":"NAME1"}]; //

alert(array1[2][1]); //4 訪問陣列中的陣列元素

alert(array1[3]1); //NAME1 訪問陣列中的物件

alert(array1[8]); //undefined

array2 = [,,]; //沒有數值填入只有逗號,則對應索引處的元素為undefined

alert(th); //3

alert(array2[1]); //undefined

用new Array()來建立陣列時,可以指定一個預設的大小,其中的值此時為undefined,以後可以再給他們賦值.但是由於

javascript中的陣列的長度是可以任意改變的,同時陣列中的內容也是可以任意改變的,因此這個初始化的長度實際上

對陣列沒有任何的約束力.對於一個數組,如果對超過它最大長度的索引賦值,則會改變陣列的長度,同時會對沒有賦值

的索引處賦值undefined,看下面的例子.

複製程式碼 程式碼如下:

var array = new Array(10);

alert(th); //10

alert(array[4]); //undefined

array[100] = "100th"; //這個操作會改變陣列的長度,同時將10-99索引對應的值設為undefined

alert(th); //101

alert(array[87]); //undefined

可以用操作符刪除陣列的元素,注意這個刪除僅僅是將陣列在該位置的元素設為undefined,陣列的長度並沒有改變.

我們已經使用過了陣列的length屬性,length屬性是一個可以讀/寫的屬性,也就是說我們可以通過改變陣列的length屬性來

任意的改變陣列的長度.如果將length設為小於陣列長度的值,則原陣列中索引大於length-1的值都會被刪除.如果length

的值大於原始陣列的長度,則在它們之間的值設為undefined.

複製程式碼 程式碼如下:

var array = new Array("n1","n2","n3","n4","n5"); //五個元素的陣列

var astring = "";

for(var i=0; i<th; i++) { //迴圈陣列元素

astring += array[i];

}

alert(astring); //n1n2n3n4n5

array[3]; //刪除陣列元素的值

alert(th + "_" + array[3]) //5_undefined

th = 3; //縮減陣列的長度

alert(array[3]); //undefined

th = 8; //擴充陣列的長度

alert(array[4]); //undefined

對於陣列的其他方法諸如join/reverse等等,在這就不再一一舉例.

通過上面的解釋,我們已經知道,物件的屬性值是通過屬性的名字(字串型別)來獲取,而陣列的元素是通過索

引(整數型 0~~2**32-1)來得到值.陣列本身也是一個物件,所以物件屬性的操作也完全適合於陣列.

複製程式碼 程式碼如下:

var array = new Array("no1","no2");

array["po"] = "props1";

alert(th); //2

//對於陣列來說,array[0]同array["0"]效果是一樣的(?不確定,測試時如此)

alert(array[0] + "_" + array["1"] + "_" + );//no1_no2_props1

陣列也是物件,所以陣列可以有自己的屬性,但是屬性和值不是一個概念,"no1"和"no2"都是陣列的值,而array["po"]是給陣列添加了一個屬性,其長度當然就沒變了。

函式

javascript函式相信大家都寫過不少了,所以我們這裡只是簡單介紹一下.

建立函式:

function f(x) {........}

var f = function(x) {......}

上面這兩種形式都可以建立名為f()的函式,不過後一種形式可以建立匿名函式

函式定義時可以設定引數,如果傳給函式的引數個數不夠,則從最左邊起依次對應,其餘的用undefined賦值,如果傳給函式

的引數多於函式定義引數的個數,則多出的引數被忽略.

複製程式碼 程式碼如下:

function myprint(s1,s2,s3) {

alert(s1+"_"+s2+"_"+s3);

}

myprint(); //undefined_undefined_undefined

myprint("string1","string2"); //string1_string2_undefined

myprint("string1","string2","string3","string4"); //string1_string2_string3

因此,對於定義好的函式,我們不能指望呼叫者將所有的引數全部傳進來.對於那些必須用到的引數應該在函式體中

加以檢測(用!操作符),或者設定預設值然後同參數進行或(||)操作來取得引數.

複製程式碼 程式碼如下:

function myprint(s1,person) {

var defaultperson = { //預設person物件

"name":"name1",

"age":18,

"sex":"female"

};

if(!s1) { //s1不允許為空

alert("s1 must be input!");

return false;

}

person = person || defaultperson; //接受person物件引數

alert(s1+"_"++":"++":"+);

};

myprint(); //s1 must be input!

myprint("s1"); //s1_name1:18:female

myprint("s1",{"name":"sdcyst","age":23,"sex":"male"}); //s1_sdcyst:23:male

函式的arguments屬性

在每一個函式體的內部,都有一個arguments識別符號,這個識別符號代表了一個Arguments物件ments物件非常類似

於Array(陣列)物件,比如都有length屬性,訪問它的值用"[]"操作符利用索引來訪問引數值,但是,二者是完全不同的

東西,僅僅是表面上有共同點而已(比如說修改Arguments物件的length屬性並不會改變它的長度).

複製程式碼 程式碼如下:

function myargs() {

alert(th);

alert(arguments[0]);

}

myargs(); //0 --- undefined

myargs("1",[1,2]); //2 --- 1

Arguments物件有一個callee屬性,標示了當前Arguments物件所在的方法.可以使用它來實現匿名函式的內部遞迴呼叫.

複製程式碼 程式碼如下:

function(x) {

if (x <= 1) return 1;

return x * ee(x-1);

} (section8.2)

Method--方法

方法就是函式.我們知道,每一個物件都包含0個或多個屬性,屬性可以是任意型別,當然也包括物件.函式本身就是一種

物件,因此我們完全可以把一個函式放到一個物件裡面,此時,這個函式就成了物件的一個方法.此後如果要使用該方法,

則可以通過物件名利用"."操作符來實現.

複製程式碼 程式碼如下:

var obj = {f0:function(){alert("f0");}}; //物件包含一個方法

function f1() {alert("f1");}

obj.f1 = f1; //為物件新增方法

obj.f0(); //f0 f0是obj的方法

obj.f1(); //f1 f1是obj的方法

f1(); //f1 f1同時又是一個函式,可以直接呼叫

f0(); //f0僅僅是obj的方法,只能通過物件來呼叫

方法的呼叫需要物件的支援,那麼在方法中如何獲取物件的屬性呢?this!this關鍵字我們已經很熟悉了,在javascript的方

法中,我們可以用this來取得對方法呼叫者(物件)的引用,從而獲取方法呼叫者的各種屬性.

複製程式碼 程式碼如下:

var obj = {"name":"NAME","sex":"female"};

t = function() { //為物件新增方法

alert( + "_" + this["sex"]);

};

t(); //NAME_female

= "male";

t(); //NAME_male

下面我們來一個更加面向物件的例子.

複製程式碼 程式碼如下:

var person = {name:"defaultname",

setName:function(s){

= s;

},

"printName":function(){

alert();

}}

tName(); //defaultname

ame("newName");

tName(); //newName

在上面的例子中,完全可以用=..來直接改變person的name屬性,在此我們只是為了展示一下剛才提到的內容.

另一種改變person屬性的方法就是:定義一個function,接收兩個引數,一個是person,一個是name的值,看起來像是這樣:

changeName(person,"newName").哪種方法好呢?很明顯,例子中的方法更形象,更直觀一些,而且好像有了那麼一點面向

物件的影子.

再次強調一下,方法(Method)本身就是是函式(function),只不過方法的使用更受限制.在後面的篇幅中,如果提到函式,那麼

提到的內容同樣適用於方法,反之則不盡然.