自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面向?qū)ο蟮腏avaScript基本知識指南大全

譯文
開發(fā) 前端
由于jQuery和MooTools等精心開發(fā)的庫,JavaScript已成為前端開發(fā)的基礎(chǔ)。不過,我們要留意這些優(yōu)秀庫中所運(yùn)用的較高級概念,這點(diǎn)極其重要。原因何在?因?yàn)樽鳛閃eb開發(fā)人員,對待學(xué)習(xí)最新的編程趨勢和試圖把那些趨勢推向極致,我們必須予以一視同仁。要不然,Web開發(fā)領(lǐng)域就不會出現(xiàn)創(chuàng)新。所以,我們不妨花點(diǎn)時(shí)間來了解JavaScript面向?qū)ο缶幊痰幕局R,包括類、繼承和范圍。

由于jQueryMooTools等精心開發(fā)的庫,JavaScript已成為前端開發(fā)的基礎(chǔ)。不過,我們要留意這些優(yōu)秀庫中所運(yùn)用的較高級概念,這點(diǎn)極其重要。原因何在?因?yàn)樽鳛閃eb開發(fā)人員,對待學(xué)習(xí)最新的編程趨勢和試圖把那些趨勢推向極致,我們必須予以一視同仁。要不然,Web開發(fā)領(lǐng)域就不會出現(xiàn)創(chuàng)新。所以,我們不妨花點(diǎn)時(shí)間來了解JavaScript面向?qū)ο缶幊痰幕局R,包括類、繼承和范圍。

在我們學(xué)習(xí)如何把類實(shí)施到代碼中之前,不妨討論一下類是什么、為什么有必要學(xué)習(xí)/使用類。

正如Java文檔聲明的那樣:“類是用來創(chuàng)建一個(gè)個(gè)對象的藍(lán)圖。”這藍(lán)圖就像造房子過程中所用的實(shí)際藍(lán)圖。建造人員使用藍(lán)圖來評估房子有什么樣的屬性,房子會有什么樣的功能。類是表示對象屬性的一種很方便的方式,無論這對象是房子、汽車還是人。當(dāng)存在的某個(gè)對象不止一個(gè)時(shí),類就變得特別有用。

比如說,我們不使用類來比較一下兩個(gè)實(shí)際的對象。這體現(xiàn)了程序思考過程,而不是面向?qū)ο蟮乃伎歼^程。我們將描述一個(gè)名叫Rob的男子和一個(gè)名為Emillee的小女孩。我們必須假定我們對人體一無所知,因?yàn)槲覀儧]有藍(lán)圖(類)可供使用。

Rob:

1. Rob在身體的上部有兩個(gè)橢圓形的結(jié)構(gòu),相隔幾英寸。這些橢圓形結(jié)構(gòu)有一個(gè)黑色背景,中間是棕色。

2. Rob有兩個(gè)與地面相對平行的結(jié)構(gòu),似乎表明了人體中最垂直的部分,這仍是身體基部的一部分。

3. Rob有兩個(gè)附屬物,從另外兩個(gè)附屬物延伸過來。這些似乎可用來抓取物件。它們似乎比較大。

4. Rob高度約6英尺。

5. Rob無意識地吸入氧,把氧轉(zhuǎn)換成二氧化碳。

Emilee:

1. Emillee在身體的上部有兩個(gè)橢圓形的結(jié)構(gòu),相隔幾英寸。這些橢圓形結(jié)構(gòu)有一個(gè)黑色背景,中間是藍(lán)色。

2. Emillee有兩個(gè)與地面相對平行的結(jié)構(gòu),似乎表明了人體中最垂直的部分,這仍是身體基部的一部分。

3. Emillee有兩個(gè)附屬物,從另外兩個(gè)附屬物延伸過來。這些似乎可用來抓取物件。它們似乎比較小。

4. Emillee高度約1.5英尺。

5. Emillee無意識地吸入氧,把氧轉(zhuǎn)換成二氧化碳。

單單描述一個(gè)人的1)眼睛、2)肩膀、3)雙手、4)身高和5)呼吸行為就有大量的工作要做。要注意:我們不得不兩次給出幾乎一模一樣的看法,因?yàn)槲覀儧]有藍(lán)圖可供使用。雖然描述兩個(gè)人不是太費(fèi)勁,但是如果我們想要描述100個(gè)人、1000個(gè)人或者100萬個(gè)人,怎么辦?肯定有一種更高效的方法來描述有著類似屬性的對象:這正是類的亮點(diǎn)。

我們不妨使用面向?qū)ο蟮睦砟睿匦驴紤]前一個(gè)例子。由于我們描述的是男子和小女孩,我們知道他們都是人類。所以不妨先為人類創(chuàng)建一個(gè)簡單的藍(lán)圖。

人類:

1. 身體的上部有兩個(gè)橢圓形的結(jié)構(gòu)。這些橢圓形結(jié)構(gòu)有一個(gè)黑色背景,中間顏色不一樣。我們稱之為眼睛。

2. 有兩個(gè)與地面相對平行的結(jié)構(gòu),似乎表明了人體中最垂直的部分,這仍是身體基部的一部分。我們稱之為肩膀。

3. 有兩個(gè)附屬物,從另外兩個(gè)附屬物延伸過來。這些似乎可用來抓取物件。它們的大小不一樣。我們稱之為雙手。

4. 視年齡及其他因素而定,高度不一樣。我們稱之為身高。

5. 無意識地吸入氧,并把氧轉(zhuǎn)換成二氧化碳。我們稱之為呼吸。

于是我們已聲明,人類的屬性是,他們有眼睛,有肩膀,有雙手,有身高。我們還已聲明,這些屬性可能不一樣。定義了人類的藍(lán)圖后,并且聲明了Rob和Emillee是人類后,我們可以將已經(jīng)知道的關(guān)于人類的屬性運(yùn)用到Rob和Emillee。

Rob是人類。

1. Rob有棕色的眼睛

2. Rob有肩膀

3. Rob有大大的雙手

4. Rob身高6英寸

5. Rob會呼吸

Emillee是人類。

1. Emillee有藍(lán)色的眼睛

2. Emillee有肩膀

3. Emillee有小小的雙手

4. Emillee身高1.5英尺

5. Emillee會呼吸

我們只要明確聲明Rob和Emillee是人類,就可以把與人類有關(guān)的屬性和功能直接運(yùn)用到Rob和Emillee。這讓我們可以避免重新定義身體的所有部位,同時(shí)讓我們可以高效地描述這兩個(gè)對象之間的重要區(qū)別。

下面是關(guān)于類及對象(名為類的實(shí)例)的幾個(gè)例子,以便你明白兩者之間的關(guān)系。

類Student(學(xué)生)

◆ 屬性:年級、年齡、出生日期和學(xué)生身份標(biāo)志(SSID)

◆ 功能:計(jì)算年級平均成績、查看缺課情況、更新操行評語

類Employee(員工)

◆ 屬性:雇主身份識別號(EIN)、小時(shí)工資、聯(lián)系號碼、保險(xiǎn)

◆ 功能:設(shè)定薪水、查看工作效率和獲取簡歷

類Computer(電腦)

◆ 屬性:處理器、主機(jī)、顯示器

◆ 功能:開機(jī)、關(guān)機(jī)和重啟

好了,我們已明白了類背后的概念,不妨把所知道的東西運(yùn)用到JavaScript。與包括PHP和C++在內(nèi)的語言不一樣,JavaScript沒有類數(shù)據(jù)類型。不過,如果我們借助JavaScript的靈活性,就很容易使用函數(shù)來模擬類。

我們以前面一個(gè)例子為例,使用類來表示學(xué)生。

創(chuàng)建一個(gè)類時(shí),你必須做兩件事:必須知道這個(gè)類有什么屬性/函數(shù)(又叫方法);你需要用一個(gè)值來初始化屬性。

  1. function Student(name, gender, age, grade, teacher) 
  2.     { 
  3.         this.name = name; 
  4.         this.gender = gender; 
  5.         this.age = age; 
  6.         this.grade = grade; 
  7.         this.teacher = teacher; 
  8.     } 
  9.     var bob = new Student("bob""male", 15, 10, "Marlow"); 
  10.     alert(bob.age); //輸出15 
  11.     var susan = new Student("susan""female", 10, 5, "Gresham"); 
  12.     alert(susan.gender); //輸出 'female' 

我們可以從這個(gè)例子中看出,類的實(shí)例使用新的運(yùn)算符來進(jìn)行初始化。類的屬性和方法使用. (dot)運(yùn)算符來訪問。所以為了獲得名為bob的Student類實(shí)例的屬性年齡,我們只要使用bob.age。同樣,我們創(chuàng)建了Student類的一個(gè)實(shí)例,把它分配給susan。為了獲得susan的性別,我們只要使用susan.gender。類在代碼可讀性方面帶來了巨大的好處:你不需要有任何編程經(jīng)驗(yàn),就能推斷出bob.age是bob的年齡。

不過,前一個(gè)例子有兩個(gè)不好(但很容易修復(fù))的缺點(diǎn)。

1)任何語句都可以訪問類屬性

2)參數(shù)必須以一定的次序來傳遞

#p#

確保屬性值的私有性

請注意:在前一個(gè)例子中,我們只要調(diào)用bob.age,就能獲得bob.age的值。此外,我們可以在程序中任何地方將bob.age設(shè)成自己喜歡的任何值。

  1. var bob = new Student("bob""male", 15, 10, "Marlow"); 
  2.     alert(bob.age); //輸出15 
  3.     bob.age = 9; 
  4.     alert(bob.age); //輸出9; 

看起來沒有害處,是不是?那么請考慮這個(gè)例子。

  1. var bob = new Student("bob""male", 15, 10, "Marlow"); 
  2. alert(bob.age); //輸出15 
  3. bob.age = -50; 
  4. alert(bob.age); //輸出-50; 

我們看到了年齡是負(fù)值:這在邏輯上不一致。我們只要使用私有變量(private variable)這個(gè)概念,就可以防止諸如此類的問題、確保數(shù)據(jù)的完整性。私有變量是只能在類本身里面訪問的變量。雖然JavaScript再次沒有用于確保變量私有性的保留字,但是JavaScript為我們提供了創(chuàng)造同樣效果的工具。

  1. function Student(name, gender, age, grade, teacher) 
  2.     { 
  3.         var studentName = name; 
  4.         var studentGender = gender; 
  5.         var studentGrade = grade; 
  6.         var studentTeacher = teacher; 
  7.         var studentAge = age; 
  8.         this.getAge = function() 
  9.         { 
  10.             return studentAge; 
  11.         }; 
  12.         this.setAge = function(val) 
  13.         { 
  14.             studentAge = Math.abs(val); //使用絕對值,確保年齡是正值 
  15.         }; 
  16.     } 
  17.     var bob = new Student("bob""male", 15, 10, "Marlow"); 
  18.     alert(bob.studentAge); //未定義,因?yàn)槟挲g在類定義中受私有保護(hù) 
  19.     alert(bob.getAge()); //輸出15 
  20.     bob.setAge(-20); 
  21.     alert(bob.getAge()); //輸出20 

通過使用變量聲明,而不是直接為類賦予屬性,我們保護(hù)了年齡數(shù)據(jù)的完整性。由于JavaScript使用了函數(shù)范圍,我們的類里面聲明的變量在該類外面是無法訪問的,除非由該類里面的函數(shù)明確返回。方法this.getAge將學(xué)生年齡返回到調(diào)用環(huán)境,它名為訪問器方法(Accessor method)。訪問器方法返回屬性的值,那樣該值就可以在類的外面使用,而不影響類里面的值。按照約定,訪問器方法的前綴通常是“get”這個(gè)字。方法this.setAge名為更改器方法(Mutator method)。其目的是,改變屬性的值,保護(hù)完整性。

我們已看到了在類里面使用訪問器方法和更改器方法來保護(hù)數(shù)據(jù)完整性的好處。不過,為每個(gè)屬性創(chuàng)建訪問器方法帶來了極其冗長的代碼。

  1. function Student(name, gender, age, grade, teacher) 
  2.     var studentName = name; 
  3.     var studentGender = gender; 
  4.     var studentGrade = grade; 
  5.     var studentTeacher = teacher; 
  6.     var studentAge = age; 
  7.     this.getName = function() 
  8.     { 
  9.         return studentName; 
  10.     }; 
  11.     this.getGender = function() 
  12.     { 
  13.         return studentGender; 
  14.     }; 
  15.     this.getGrade = function() 
  16.     { 
  17.         return studentGrade; 
  18.     }; 
  19.     this.getTeacher = function() 
  20.     { 
  21.         return studentTeacher; 
  22.     }; 
  23.     this.getAge = function() 
  24.     { 
  25.         return studentAge; 
  26.     }; 
  27.     this.setAge = function(val) 
  28.     { 
  29.         studentAge = Math.abs(val); //使用絕對值,確保年齡是正值 
  30.     }; 
  31. var bob = new Student("bob""male", 15, 10, "Marlow"); 
  32. alert(bob.studentGender); //未定義,因?yàn)樾詣e在類定義中受私有保護(hù) 
  33. alert(bob.getGender()); //輸出 'male' 

教我C++的教授總是說:“如果你發(fā)現(xiàn)自己反復(fù)輸入相同的代碼,這表明你的做法不對。”的確,有更高效的方法可以為每個(gè)屬性創(chuàng)建訪問器方法。此外,這種機(jī)制還不需要以特定次序來調(diào)用函數(shù)參數(shù)。

動(dòng)態(tài)創(chuàng)建的訪問器方法

這個(gè)演示來自John Resig所寫的《專業(yè)JavaScript技巧》一書(我強(qiáng)烈建議各位讀一讀。前三章就非常值得一讀)。

  1. function Student( properties ) 
  2.     { 
  3.         var $this = this;  //將類范圍存儲到名為$this的變量中 
  4.         //迭代處理對象的屬性 
  5.         for ( var i in properties ) 
  6.         { 
  7.             (function(i) 
  8.             { 
  9.                 // 動(dòng)態(tài)創(chuàng)建訪問器方法 
  10.                 $this"get" + i ] = function() 
  11.                 { 
  12.                     return properties[i]; 
  13.                 }; 
  14.             })(i); 
  15.         } 
  16.     } 
  17.     // 創(chuàng)建一個(gè)新的用戶對象實(shí)例,并傳遞屬性的對象 
  18.     var student = new Student( 
  19.     { 
  20.         Name: "Bob"
  21.         Age: 15, 
  22.         Gender: "male" 
  23.     }); 
  24.     alert(student.name); //因?qū)傩允撬接械亩炊x 
  25.     alert(student.getName()); //輸出 "Bob" 
  26.     alert(student.getAge()); //輸出15 
  27.     alert(student.getGender()); //輸出 "male" 

通過實(shí)施這個(gè)技巧,我們不但確保自己的屬性是私有的,而且不需要按次序來指定參數(shù)。下面的類實(shí)例化都相同:

  1. var student = new Student( 
  2.     { 
  3.         Name: "Bob"
  4.         Age: 15, 
  5.         Gender: "male" 
  6.     }); 
  7.     var student = new Student( 
  8.     { 
  9.         Age: 15, 
  10.         Name: "Bob"
  11.         Gender: "male" 
  12.     }); 
  13.     var student = new Student( 
  14.     { 
  15.         Gender: "male"
  16.         Age: 15, 
  17.         Name: "Bob" 
  18.     }); 

#p#

繼承

在這篇文章中,我使用“類”這個(gè)術(shù)語極其寬松。如前所述,JavaScript沒有類實(shí)體,但是后面仍可以跟類的模式。JavaScript與其他面向?qū)ο笳Z言的區(qū)別主要在于繼承模型。C++和Java體現(xiàn)了基于類的繼承或傳統(tǒng)繼承。另一方面,JavaScript體現(xiàn)了原型繼承(Prototypal Inheritance)。在其他面向?qū)ο笳Z言中,類是一個(gè)實(shí)際的數(shù)據(jù)類型,表示創(chuàng)建對象的藍(lán)圖。在JavaScript中,雖然我們可以使用函數(shù)來模擬對象藍(lán)圖,但是它們實(shí)際上本身就是對象。然后,這些對象用作其他對象的模型(又叫原型),可以參閱文章《JavaScript原型繼承》(http://www.webreference.com/programming/javascript/prototypal_inheritance/index.html)。

運(yùn)用原型繼承這個(gè)概念讓我們得以創(chuàng)建“子類”,即繼承另一個(gè)對象的屬性的對象。如果我們想使用另一個(gè)對象的稍有一些變動(dòng)的方法,這就變得極其有用。

以類Employee(員工)為例。假設(shè)我們有兩種類型的員工:一種基于薪水,一種基于傭金。這些員工類型會有許多相似的屬性。比如說,不管某員工通過傭金獲得收入還是通過薪水獲得收入,該員工都有名稱。不過,對基于傭金的員工和基于薪水的員工來說,收入方式完全不一樣。下面這個(gè)例子體現(xiàn)了這個(gè)概念:

  1. function Worker() 
  2.     this.getMethods = function(properties, scope) 
  3.     { 
  4.         var $this = scope;  //將類范圍存儲到名為$this的變量中 
  5.         //迭代處理對象的屬性 
  6.         for ( var i in properties ) 
  7.         { 
  8.             (function(i) 
  9.             { 
  10.                 // 動(dòng)態(tài)創(chuàng)建訪問器方法 
  11.                 $this"get" + i ] = function() 
  12.                 { 
  13.                     return properties[i]; 
  14.                 }; 
  15.             //動(dòng)態(tài)地創(chuàng)建一個(gè)分析整數(shù),并確保是正值的更改器方法。 
  16.             $this"set" + i ] = function(val) 
  17.             { 
  18.                 if(isNaN(val)) 
  19.                 { 
  20.                     properties[i] = val; 
  21.                 } 
  22.                 else 
  23.                 { 
  24.                     properties[i] = Math.abs(val); 
  25.                 } 
  26.             }; 
  27.             })(i); 
  28.         } 
  29.     }; 
  30. // CommissionWorker "子類"和WageWorker "子類" 
  31. //繼承Worker的屬性和方法。 
  32. CommissionWorker.prototype = new Worker(); 
  33. WageWorker.prototype = new Worker(); 
  34. function CommissionWorker(properties) 
  35.     this.getMethods(properties, this); 
  36.     //計(jì)算收入 
  37.     this.getIncome = function() 
  38.     { 
  39.         return properties.Sales * properties.Commission; 
  40.     } 
  41. //要求有下列屬性:薪水、每周小時(shí)數(shù)、每年周數(shù) 
  42. function WageWorker(properties) 
  43.     this.getMethods(properties, this); 
  44.     //計(jì)算收入 
  45.     this.getIncome = function() 
  46.     { 
  47.         return properties.Wage * properties.HoursPerWeek * properties.WeeksPerYear; 
  48.     } 
  49. var worker = new WageWorker( 
  50.     Name: "Bob"
  51.     Wage: 10, 
  52.     HoursPerWeek: 40, 
  53.     WeeksPerYear: 48 
  54. }); 
  55. alert(worker.wage); //未定義。薪水是私有屬性。 
  56. worker.setWage(20); 
  57. alert(worker.getName());   //輸出 "Bob" 
  58. alert(worker.getIncome()); //輸出 38,400 (20*40*48) 
  59. var worker2 = new CommissionWorker( 
  60.     Name: "Sue"
  61.     Commission: .2, 
  62.     Sales: 40000 
  63. }); 
  64. alert(worker2.getName());   //輸出 "Sue" 
  65. alert(worker2.getIncome()); //輸出8000(2% 乘40,000) 

前一個(gè)例子中最重要的兩個(gè)語句是:

  1. CommissionWorker.prototype = new Worker(); 
  2. WageWorker.prototype = new Worker(); 

這聲明,對新的CommissionWorker或新的WageWorker對象的每個(gè)實(shí)例而言,Worker的屬性和方法將傳遞到那些新對象。如果需要的話,這些方法和屬性可以在“子類”定義里面被覆蓋寫入。

范圍

JavaScript體現(xiàn)了所謂的函數(shù)范圍。這意味著,函數(shù)中聲明的變量在函數(shù)(變量來自該函數(shù))外面最初是無法訪問的。不過,在語句塊中(如條件語句),可以對調(diào)用環(huán)境進(jìn)行變量聲明或改動(dòng)。

  1. var car = "Toyota"
  2.     if(car == "Toyota"
  3.     { 
  4.         car = "Toyota - We never stop...and you won't either."
  5.     } 
  6.     alert(car); //輸出Toyota——我們從未停上,你也如此。 
  7.     car = "Toyota"//將汽車設(shè)回成原始值。 
  8.     function makeFord(car) 
  9.     { 
  10.         car = "Ford"
  11.     } 
  12.     makeFord(car); 
  13.     alert(car); //輸出"Toyota",因?yàn)槠囋诤瘮?shù)范圍中已改動(dòng)。 

不過,如果你想要改動(dòng)值的函數(shù),可以將對象作為參數(shù)來傳遞,并改動(dòng)對象的屬性。

  1. var car = new Object(); 
  2.     car.brand = "Toyota" 
  3.     function makeFord(car) 
  4.     { 
  5.         car.brand = "Ford"
  6.     } 
  7.     makeFord(car); 
  8.     alert(car.brand); //輸出“Ford” 

這名為“通過調(diào)用”傳遞,將值傳遞給函數(shù)。只有你在類里面創(chuàng)建方法,又知道對象含有什么屬性,我一般才會建議采用通過調(diào)用傳遞。

現(xiàn)在你已經(jīng)掌握了運(yùn)用到JavaScript的面向?qū)ο蟮幕局R。運(yùn)用這些原則,就可以為你在將來的開發(fā)項(xiàng)目簡化代碼。

原文:http://www.1stwebdesigner.com/design/object-oriented-basics-javascript/

【編輯推薦】

  1. 10個(gè)令人驚奇的HTML5和JavaScript效果
  2. 非常全面的實(shí)用JavaScript開發(fā)工具列表
  3. 一位反JavaScript主義者的覺醒
  4. JavaScript函數(shù)式編程
  5. JavaScript入門
責(zé)任編輯:陳貽新 來源: 51CTO
相關(guān)推薦

2017-02-20 23:05:14

JavaScript

2010-05-25 14:05:52

MySQL數(shù)據(jù)庫

2011-11-23 10:35:53

2010-07-28 15:52:00

Flex

2009-06-11 14:40:32

Java list

2010-05-06 17:41:19

Unix命令

2017-04-12 11:47:32

2017-10-20 22:40:54

電線電纜導(dǎo)體

2009-06-26 14:42:08

2009-08-28 16:53:05

C# for語句

2019-11-18 17:05:02

JavaScript面向?qū)ο蟪绦蚓幊?/a>Java

2009-12-22 14:43:38

Linux操作系統(tǒng)

2010-01-28 11:18:14

Android界面布局

2010-06-13 13:49:14

2012-06-05 00:41:07

JavaJava內(nèi)存

2010-04-21 18:38:36

Unix網(wǎng)絡(luò)

2010-06-10 11:41:57

MPLS協(xié)議棧結(jié)構(gòu)

2011-04-29 13:50:32

激光打印機(jī)

2020-07-20 07:10:44

數(shù)據(jù)中心IT技術(shù)

2021-10-21 18:47:37

JavaScript面向對象
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號