[推薦]javascript 物件導向技術基礎教程

來源:互聯網
上載者:User

結果呢,看了大半天,有了一個大概的瞭解,細細一回味,好像什麼都沒懂...
這篇文章是參考<<javascript-the definitive guide,5th edition>>第7,8,9章而寫成的,我也
會盡量按照原書的結構來說明javascript的物件導向技術(對象/數組->函數-->類/建構函式/原型).對一些我自己也拿捏不準的地方,我會附上原文的英文語句,供大家參考.
如果不做說明,則文中出現的所有英文語句(程式體除外)都是引自<<javascript-the definitive guide,5th edition>>.
-------------------------------------------------
對象和數組(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()來建立一個Null 物件,也可以簡單的用"{}"來建立一個
Null 物件,這兩者的作用是等同的.

複製代碼 代碼如下:var emptyObject1 = {}; //建立Null 物件
var emptyObject2 = new Object(); //建立Null 物件
var person = {"name":"sdcyst",
"age":18,
"sex":"male"}; //建立一個包含初始值的對象person
alert(person.name); //sdcyst
alert(person["age"]); //18

從上面的例子我們也可以看到,訪問一個對象的屬性,可以簡單的用對象名加"."後加屬性的名字,也可以用"[]"操作符來擷取,此時在[]裡面的屬性名稱字要加引號,這是因為對象中的索引都是字串類型的. javasript對象中屬性的個數是可變的,在建立了一個對象之後可以隨時對它賦予任何的屬性. 複製代碼 代碼如下:var person = {};
person.name = "sdcyst";
person["age"] = 18;
alert(person.name + "__" + person.age); //sdcyst__18
var _person = {name:"balala","age":23}; //在構建一個對象時,屬性的名字可以不用引號來標註(name),
//但是仍舊是一個字串類型.在訪問的時候[]內仍舊需要引號
alert(_person["name"] + "__" + person.age); //balala__23
alert(_person[name]); //undefinied
var person = {};
person.name = "sdcyst";
person["age"] = 18;
alert(person.name + "__" + person.age); //sdcyst__18
var _person = {name:"balala","age":23}; //在構建一個對象時,屬性的名字可以不用引號來標註(name),
//但是仍舊是一個字串類型.在訪問的時候[]內仍舊需要引號
alert(_person["name"] + "__" + person.age); //balala__23
alert(_person[name]); //undefinied

通過"."操作符擷取對象的屬性,必須得知道屬性的名字.一般來說"[]"操作符擷取對象屬性的功能更強大一些,

可以在[]中放入一些運算式來取屬性的值,
比如可以用在迴圈控制語句中,而"."操作符則沒有這種靈活性。 複製代碼 代碼如下: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

delete操作符可以刪除對象中的某個屬性,判斷某個屬性是否存在可以使用"in"操作符. 複製代碼 代碼如下:var name = {"name1":"NAME1","name2":"NAME2","name3":"NAME3","name4":"NAME4"};
var namestring = "";
for(var props in name) { //迴圈name對象中的屬性名稱字
namestring += name[props];
}
alert(namestring); //NAME1NAME2NAME3NAME4

delete name.name1; //刪除name1屬性
delete 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屬性.這個屬性對應了對象初始化時的建構函式(函數也是對象). 複製代碼 代碼如下:var date = new Date();
alert(date.constructor); //Date
alert(date.constructor == "Date"); //false
alert(date.constructor == 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 programming.To 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一個.

Js代碼 複製代碼 代碼如下:var array1 = []; //建立空數組
var array2 = new Array(); //建立空數組
array1 = [1,"s",[3,4],{"name1":"NAME1"}]; //
alert(array1[2][1]); //4 訪問數組中的數組元素
alert(array1[3].name1); //NAME1 訪問數組中的對象
alert(array1[8]); //undefined
array2 = [,,]; //沒有數值填入只有逗號,則對應索引處的元素為undefined
alert(array2.length); //3
alert(array2[1]); //undefined
var array1 = []; //建立空數組
var array2 = new Array(); //建立空數組
array1 = [1,"s",[3,4],{"name1":"NAME1"}]; //
alert(array1[2][1]); //4 訪問數組中的數組元素
alert(array1[3].name1); //NAME1 訪問數組中的對象
alert(array1[8]); //undefined
array2 = [,,]; //沒有數值填入只有逗號,則對應索引處的元素為undefined
alert(array2.length); //3
alert(array2[1]); //undefined

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

javascript中的數組的長度是可以任意改變的,同時數組中的內容也是可以任意改變的,因此這個初始化的長度實際上
對數組沒有任何的約束力.對於一個數組,如果對超過它最大長度的索引賦值,則會改變數組的長度,同時會對沒有賦值
的索引處賦值undefined,看下面的例子.

Js代碼 複製代碼 代碼如下:var array = new Array(10);
alert(array.length); //10
alert(array[4]); //undefined
array[100] = "100th"; //這個操作會改變數組的長度,同時將10-99索引對應的值設為undefined
alert(array.length); //101
alert(array[87]); //undefined
var array = new Array(10);
alert(array.length); //10
alert(array[4]); //undefined
array[100] = "100th"; //這個操作會改變數組的長度,同時將10-99索引對應的值設為undefined
alert(array.length); //101
alert(array[87]); //undefined

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

我們已經使用過了數組的length屬性,length屬性是一個可以讀/寫的屬性,也就是說我們可以通過改變數組的length屬性來
任意的改變數組的長度.如果將length設為小於數組長度的值,則原數組中索引大於length-1的值都會被刪除.如果length
的值大於原始數組的長度,則在它們之間的值設為undefined.

Js代碼 複製代碼 代碼如下:var array = new Array("n1","n2","n3","n4","n5"); //五個元素的數組
var astring = "";
for(var i=0; i<array.length; i++) { //迴圈數組元素
astring += array[i];
}
alert(astring); //n1n2n3n4n5
delete array[3]; //刪除數組元素的值
alert(array.length + "_" + array[3]) //5_undefined

array.length = 3; //縮減數組的長度
alert(array[3]); //undefined
array.length = 8; //擴充數組的長度
alert(array[4]); //undefined
var array = new Array("n1","n2","n3","n4","n5"); //五個元素的數組
var astring = "";
for(var i=0; i<array.length; i++) { //迴圈數組元素
astring += array[i];
}
alert(astring); //n1n2n3n4n5
delete array[3]; //刪除數組元素的值
alert(array.length + "_" + array[3]) //5_undefined

array.length = 3; //縮減數組的長度
alert(array[3]); //undefined
array.length = 8; //擴充數組的長度
alert(array[4]); //undefined

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

通過上面的解釋,我們已經知道,對象的屬性值是通過屬性的名字(字串類型)來擷取,而數組的元素是通過索
引(整數型 0~~2**32-1)來得到值.數組本身也是一個對象,所以對象屬性的操作也完全適合於數組.

Js代碼 複製代碼 代碼如下:var array = new Array("no1","no2");
array["po"] = "props1";
alert(array.length); //2
//對於數組來說,array[0]同array["0"]效果是一樣的(?不確定,測試時如此)
alert(array[0] + "_" + array["1"] + "_" + array.po);//no1_no2_props1

函數
javascript函數相信大家都寫過不少了,所以我們這裡只是簡單介紹一下.
建立函數: 複製代碼 代碼如下:function f(x) {........}
var f = function(x) {......}

上面這兩種形式都可以建立名為f()的函數,不過後一種形式可以建立匿名函數
函數定義時可以設定參數,如果傳給函數的參數個數不夠,則從最左邊起依次對應,其餘的用undefined賦值,如果傳給函數
的參數多於函數定義參數的個數,則多出的參數被忽略.

Js代碼 複製代碼 代碼如下: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,s2,s3) {
alert(s1+"_"+s2+"_"+s3);
}
myprint(); //undefined_undefined_undefined
myprint("string1","string2"); //string1_string2_undefined
myprint("string1","string2","string3","string4"); //string1_string2_string3

因此,對於定義好的函數,我們不能指望調用者將所有的參數全部傳進來.對於那些必須用到的參數應該在函數體中
加以檢測(用!操作符),或者設定預設值然後同參數進行或(||)操作來取得參數.

Js代碼 複製代碼 代碼如下: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+"_"+person.name+":"+person.age+":"+person.sex);
};

myprint(); //s1 must be input!
myprint("s1"); //s1_name1:18:female
myprint("s1",{"name":"sdcyst","age":23,"sex":"male"}); //s1_sdcyst:23:male
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+"_"+person.name+":"+person.age+":"+person.sex);
};

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對象.Arguments對象非常類似
於Array(數組)對象,比如都有length屬性,訪問它的值用"[]"操作符利用索引來訪問參數值,但是,二者是完全不同的
東西,僅僅是表面上有共同點而已(比如說修改Arguments對象的length屬性並不會改變它的長度).

Js代碼 複製代碼 代碼如下:function myargs() {
alert(arguments.length);
alert(arguments[0]);
}
myargs(); //0 --- undefined
myargs("1",[1,2]); //2 --- 1
function myargs() {
alert(arguments.length);
alert(arguments[0]);
}
myargs(); //0 --- undefined
myargs("1",[1,2]); //2 --- 1 Arguments對象有一個callee屬性,標示了當前Arguments對象所在的方法.可以使用它來實現匿名函數的內部遞迴調用.

Js代碼 複製代碼 代碼如下:function(x) {
if (x <= 1) return 1;
return x * arguments.callee(x-1);
} (section8.2)
function(x) {
if (x <= 1) return 1;
return x * arguments.callee(x-1);
} (section8.2)

Method--方法
方法就是函數.我們知道,每一個對象都包含0個或多個屬性,屬性可以是任意類型,當然也包括對象.函數本身就是一種
對象,因此我們完全可以把一個函數放到一個對象裡面,此時,這個函數就成了對象的一個方法.此後如果要使用該方法,
則可以通過對象名利用"."操作符來實現.

Js代碼 複製代碼 代碼如下: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的方法,只能通過對象來調用
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來取得對方法調用者(對象)的引用,從而擷取方法調用者的各種屬性.

Js代碼 複製代碼 代碼如下:var obj = {"name":"NAME","sex":"female"};
obj.print = function() { //為對象添加方法
alert(this.name + "_" + this["sex"]);
};
obj.print(); //NAME_female
obj.sex = "male";
obj.print(); //NAME_male
var obj = {"name":"NAME","sex":"female"};
obj.print = function() { //為對象添加方法
alert(this.name + "_" + this["sex"]);
};
obj.print(); //NAME_female
obj.sex = "male";
obj.print(); //NAME_male

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

Js代碼 複製代碼 代碼如下:var person = {name:"defaultname",
setName:function(s){
this.name = s;
},
"printName":function(){
alert(this.name);
}}
person.printName(); //defaultname
person.setName("newName");
person.printName(); //newName
var person = {name:"defaultname",
setName:function(s){
this.name = s;
},
"printName":function(){
alert(this.name);
}}
person.printName(); //defaultname
person.setName("newName");
person.printName(); //newName

在上面的例子中,完全可以用person.name=..來直接改變person的name屬性,在此我們只是為了展示一下剛才提到的內容.
另一種改變person屬性的方法就是:定義一個function,接收兩個參數,一個是person,一個是name的值,看起來像是這樣:
changeName(person,"newName").哪種方法好呢?很明顯,例子中的方法更形象,更直觀一些,而且好像有了那麼一點面向
對象的影子.

再次強調一下,方法(Method)本身就是是函數(function),只不過方法的使用更受限制.在後面的篇幅中,如果提到函數,那麼
提到的內容同樣適用於方法,反之則不盡然.

函數的prototype屬性
每一個函數都包含了一個prototype(原型)屬性,這個屬性構成了javascript物件導向的核心基礎.在後面我們會詳細討論.

相關文章

聯繫我們

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