javascript面向?qū)ο蠹夹g(shù)基礎(chǔ)(三)
看了很多介紹javascript面向?qū)ο蠹夹g(shù)的文章,很暈.為什么?不是因?yàn)閷懙貌缓?而是因?yàn)樘願(yuàn)W.javascript中的對(duì)象還沒解釋清楚怎么回事,一上來就直奔主題,類/繼承/原型/私有變量。結(jié)果呢,看了大半天,有了一個(gè)大概的了解,細(xì)細(xì)一回味,好像什么都沒懂。
這篇文章是參考<<javascript-the definitive guide,5th edition>>第7,8,9章而寫成的,我也會(huì)盡量按照原書的結(jié)構(gòu)來說明javascript的面向?qū)ο蠹夹g(shù)(對(duì)象/數(shù)組->函數(shù)-->類/構(gòu)造函數(shù)/原型).對(duì)一些我自己也拿捏不準(zhǔn)的地方,我會(huì)附上原文的英文語句,供大家參考.
如果不做說明,則文中出現(xiàn)的所有英文語句(程序體除外)都是引自<<javascript-the definitive guide,5th edition>>.
函數(shù)
javascript函數(shù)相信大家都寫過不少了,所以我們這里只是簡(jiǎn)單介紹一下.
創(chuàng)建函數(shù):
function f(x) {........}
var f = function(x) {......}
上面這兩種形式都可以創(chuàng)建名為f()的函數(shù),不過后一種形式可以創(chuàng)建匿名函數(shù),函數(shù)定義時(shí)可以設(shè)置參數(shù),如果傳給函數(shù)的參數(shù)個(gè)數(shù)不夠,則從最左邊起依次對(duì)應(yīng),其余的用undefined賦值,如果傳給函數(shù)的參數(shù)多于函數(shù)定義參數(shù)的個(gè)數(shù),則多出的參數(shù)被忽略.
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
因此,對(duì)于定義好的函數(shù),我們不能指望調(diào)用者將所有的參數(shù)全部傳進(jìn)來.對(duì)于那些必須用到的參數(shù)應(yīng)該在函數(shù)體中加以檢測(cè)(用!操作符),或者設(shè)置默認(rèn)值然后同參數(shù)進(jìn)行或(||)操作來取得參數(shù).
Js代碼
- function myprint(s1,person) {
- var defaultperson = { //默認(rèn)person對(duì)象
- "name":"name1",
- "age":18,
- "sex":"female"
- };
- if(!s1) { //s1不允許為空
- alert("s1 must be input!");
- return false;
- }
- person = person || defaultperson; //接受person對(duì)象參數(shù)
- 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
函數(shù)的arguments屬性
在每一個(gè)函數(shù)體的內(nèi)部,都有一個(gè)arguments標(biāo)識(shí)符,這個(gè)標(biāo)識(shí)符代表了一個(gè)Arguments對(duì)象.Arguments對(duì)象非常類似于Array(數(shù)組)對(duì)象,比如都有l(wèi)ength屬性,訪問它的值用"[]"操作符利用索引來訪問參數(shù)值,但是,二者是完全不同的東西,僅僅是表面上有共同點(diǎn)而已(比如說修改Arguments對(duì)象的length屬性并不會(huì)改變它的長(zhǎng)度).
Js代碼
- function myargs() {
- alert(arguments.length);
- alert(arguments[0]);
- }
- myargs(); //0 --- undefined
- myargs("1",[1,2]); //2 --- 1
Arguments對(duì)象有一個(gè)callee屬性,標(biāo)示了當(dāng)前Arguments對(duì)象所在的方法.可以使用它來實(shí)現(xiàn)匿名函數(shù)的內(nèi)部遞歸調(diào)用.
Js代碼
- function(x) {
- if (x <= 1) return 1;
- return x * arguments.callee(x-1);
- }
Method--方法
方法就是函數(shù).我們知道,每一個(gè)對(duì)象都包含0個(gè)或多個(gè)屬性,屬性可以是任意類型,當(dāng)然也包括對(duì)象.函數(shù)本身就是一種對(duì)象,因此我們完全可以把一個(gè)函數(shù)放到一個(gè)對(duì)象里面,此時(shí),這個(gè)函數(shù)就成了對(duì)象的一個(gè)方法.此后如果要使用該方法,則可以通過對(duì)象名利用"."操作符來實(shí)現(xiàn).
Js代碼
- var obj = {f0:function(){alert("f0");}}; //對(duì)象包含一個(gè)方法
- function f1() {alert("f1");}
- obj.f1 = f1; //為對(duì)象添加方法
- obj.f0(); //f0 f0是obj的方法
- obj.f1(); //f1 f1是obj的方法
- f1(); //f1 f1同時(shí)又是一個(gè)函數(shù),可以直接調(diào)用
- f0(); //f0僅僅是obj的方法,只能通過對(duì)象來調(diào)用
方法的調(diào)用需要對(duì)象的支持,那么在方法中如何獲取對(duì)象的屬性呢?this!this關(guān)鍵字我們已經(jīng)很熟悉了,在javascript的方法中,我們可以用this來取得對(duì)方法調(diào)用者(對(duì)象)的引用,從而獲取方法調(diào)用者的各種屬性.
Js代碼
- var obj = {"name":"NAME","sex":"female"};
- obj.print = function() { //為對(duì)象添加方法
- alert(this.name + "_" + this["sex"]);
- };
- obj.print(); //NAME_female
- obj.sex = "male";
- obj.print(); //NAME_male
下面我們來一個(gè)更加面向?qū)ο蟮睦?
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
在上面的例子中,完全可以用person.name=..來直接改變person的name屬性,在此我們只是為了展示一下剛才提到的內(nèi)容.另一種改變person屬性的方法就是:定義一個(gè)function,接收兩個(gè)參數(shù),一個(gè)是person,一個(gè)是name的值,看起來像是這樣:changeName(person,"newName").哪種方法好呢?很明顯,例子中的方法更形象,更直觀一些,而且好像有了那么一點(diǎn)面向?qū)ο蟮挠白?
再次強(qiáng)調(diào)一下,方法(Method)本身就是是函數(shù)(function),只不過方法的使用更受限制.在后面的篇幅中,如果提到函數(shù),那么
提到的內(nèi)容同樣適用于方法,反之則不盡然.
函數(shù)的prototype屬性
每一個(gè)函數(shù)都包含了一個(gè)prototype(原型)屬性,這個(gè)屬性構(gòu)成了javascript面向?qū)ο蟮暮诵幕A(chǔ).在后面我們會(huì)詳細(xì)討論.
【編輯推薦】