學好JS的面向對象,能很大程度上提高代碼的重用率,像jQuery,easyui等,這篇博客主要從細節上一步步講JS中如何有效地創建對象,也可以看到常見的創建對象的方式,最後也會附上一些JS面向對象的案例。
一、面向對象(Java面向對象亦是如此)
1.對象:對象是一個整體,對外提供一些操作。
2.面向對象:使用對象時,只關注對象提供的功能,不關注其內部細節。比如電腦——有鼠標、鍵盤,我們只需要知道怎麼使用鼠標,敲打鍵盤即可,不必知道爲何點擊鼠標可以選中、敲打鍵盤是如何輸入文字以及屏幕是如何顯示文字的。總之我們沒必要知道其具體工作細節,只需知道如何使用其提供的功能即可,這就是面向對象。
3.JS的對象組成:方法 和 屬性
在JS中,有函數、方法、事件處理函數、構造函數,其實這四個都是函數,只是作用不同。函數是獨立的存在,方法屬於一個對象,事件處理函數用來處理一個事件,構造函數用來構造對象。
首先通過常用的數組來認識下JS的對象:
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="UTF-8">
5 <title></title>
6 <script>
7
8 /**
9 * 定義一個數組
10 */
11 var arr = [1, 2, 3, 4, 5];
12
13 /**
14 * 彈出 object
15 * 說明數組就是個對象
16 */
17 alert(typeof arr);
18
19 /**
20 * 彈出5
21 * 對象的屬性 length
22 */
23 alert(arr.length);
24
25 /**
26 * 對象的方法 push
27 * 彈出 1,2,3,4,5,6
28 */
29 arr.push(6);
30 alert(arr);
31 </script>
32 </head>
33 <body>
34 </body>
35 </html>
4.認識下JS中的this以及全局對象window
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="UTF-8">
5 <title></title>
6 <script>
7 /**
8 * 定義一個全局函數
9 */
10 function show(){
11 alert(this);
12 }
13 //調用show()
14 show();
15
16 </script>
17 </head>
18 <body>
19 </body>
20 </html>
此處的show()函數爲一個全局函數,調用show(),alert(this)彈出來的是window對象,說明全局函數屬於window。上面定義的show()等於爲window添加一個方法,全局的函數和變量都是屬於window的,上面的定義等價於下面。
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <script>
5 /**
6 * 爲window定義一個show方法
7 */
8 window.show = function(){
9 alert(this);
10 }
11 //調用show()
12 window.show();
13
14 </script>
15 </head>
16 </html>
同樣的我們也可以根據自己的需求爲其它的對象添加方法,比如顯示數組:
但是我們不能在系統對象中隨意附加方法和屬性,否則可能會覆蓋已有方法、屬性。
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <script>
5 var arr = [1,2,3,4,5];
6 arr.show = function(){
7 alert(this);
8 }
9 arr.show(); //彈出 1,2,3,4,5
10 </script>
11 </head>
12 </html>
從上面的例子也可以看出來,this即表示當前函數的調用者是誰,但是在一種情況下不是的,就是使用new 來創建對象時,this並不是指向調用者的,在後面會有說明。
window是全局對象,可以看下屬於window的全局屬性和全局方法:
二、JS中自定義對象,逐步分析JS中的創建對象
1.通過Object創建簡單對象:
這種方式有一個非常大的弊端,就是如果我有多個人怎麼辦,每次都要新建一個對象,然後添加屬性、方法,這種方式是一次性的,會產生大量重複代碼,這是不可取的。
1 <!DOCTYPE html>
2 <html>
3 <meta charset="UTF-8" />
4 <head>
5 <script>
6 /**
7 * 創建一個新對象
8 * new Object()創建出來的對象幾乎是空白的,需要自己添加屬性,方法
9 */
10 var person = new Object();
11 //爲person對象添加屬性
12 person.name = "jiangzhou";
13 person.age = 22;
14 //爲person對象添加方法
15 person.showName = function(){
16 alert("姓名:"+this.name);
17 }
18 person.showAge = function(){
19 alert("年齡:"+this.age);
20 }
21 //調用對象的方法
22 person.showName();
23 person.showAge();
24
25 </script>
26 </head>
27 </html>
2.用工廠方式來構造對象:工廠,簡單來說就是投入原料、加工、出廠。
通過構造函數來生成對象,將重複的代碼提取到一個函數裏面,避免像第一種方式寫大量重複的代碼。這樣我們在需要這個對象的時候,就可以簡單地創建出來了。
1 <!DOCTYPE html>
2 <html>
3 <meta charset="UTF-8" />
4 <head>
5 <script>
6 //構造函數:工廠
7 function createPerson(name, age){
8 var person = new Object();
9
10 //原料
11 person.name = name;
12 person.age = age;
13
14 //加工
15 person.showName = function(){
16 alert("姓名:"+this.name);
17 }
18 person.showAge = function(){
19 alert("年齡:"+this.age);
20 }
21 //出廠
22 return person;
23 }
24 //創建兩個對象
25 var p1 = createPerson("jiangzhou", 22);
26 var p2 = createPerson("tom", 20);
27
28 //調用對象方法
29 p1.showName();
30 p1.showAge();
31
32 p2.showName();
33 p2.showAge();
34
35 </script>
36 </head>
37 </html>
但是,這種方式有兩個缺點:
①一般我們創建對象是通過new來創建,比如new Date(),這裏使用的是方法創建。使用new來創建可以簡化一些代碼,也帶來一些新的特性。
②每個對象都有一套自己的方法,浪費資源(雖然對於現在的計算機來說不算什麼,但我們儘量將設計做到最好就行了)。
這裏爲什麼說每個對象都有自己的一套方法呢,是因爲創建function()的時候其本質是通過new Function()來創建的,會誕生一個新的函數對象,所以每個對象的方法是不一樣的,這樣就存在資源浪費的問題了。看第25行代碼。
1 <!DOCTYPE html>
2 <html>
3 <meta charset="UTF-8" />
4 <head>
5 <script>
6
7 function createPerson(name, age, sex){
8 var person = new Object();
9
10 person.name = name;
11 person.age = age;
12 person.sex = sex;
13
14 person.showName = function(){
15 alert("姓名:"+this.name);
16 }
17 person.showAge = function(){
18 alert("年齡:"+this.age);
19 }
20
21 /**
22 * person.showSex = function(){} 等價於 person.showSex = new Function('');
23 * 也就是說我們在創建這個函數的時候就是新建了一個對象。
24 */
25 person.showSex = new Function('alert("性別:"+this.sex)');
26
27 return person;
28 }
29
30 //創建兩個對象
31 var p1 = createPerson("jiangzhou", 22, "男");
32 var p2 = createPerson("Lyli", 20, "女");
33
34 alert(p1.showName == p2.showName); //false
35
36 </script>
37 </head>
38 </html>
3.使用new 來創建JS對象
1 <!DOCTYPE html>
2 <html>
3 <meta charset="UTF-8" />
4 <head>
5 <script>
6
7 function Person(name, age){
8 /**
9 * 可以假想成系統會創建一個對象
10 * var this = new Object();
11 */
12
13 alert(this); //彈出Object
14
15 this.name = name;
16 this.age = age;
17
18 this.showName = function(){
19 alert("姓名:"+this.name);
20 }
21 this.showAge = function(){
22 alert("年齡:"+this.age);
23 }
24
25 /**
26 * 假想返回了對象
27 * return this;
28 */
29 }
30
31 //創建兩個對象
32 var p1 = new Person("jiangzhou", 22);//可以看到在外面new了在function裏面就不用new了;在function裏面new了,在外面就不用new了;O(∩_∩)O~
33 var p2 = new Person("Lyli", 20);
34
35 alert(p1.showName == p2.showName); //false
36
37 </script>
38 </head>
39 </html>
彈出信息顯示this即是一個Object(第13行代碼)。在方法調用前使用new來創建,function內的this會指向一個新創建的空白對象,而不是指向方法調用者,而且會自動返回該對象。
但是這種方式只解決了第一個問題,每個對象還是有自己的一套方法(第35行代碼)。
4.在function原型(prototype)上進行擴展 —— 最終版
原型添加的方法不會有多個副本,不會浪費資源,所有的對象只有一套方法(看第29行代碼)。 至於爲什麼是用的一套方法呢,看第31行代碼:因爲所有的方法都等於原型上的方法。
1 <!DOCTYPE html>
2 <html>
3 <meta charset="UTF-8" />
4 <head>
5 <script>
6
7 /**
8 * Person構造函數:在JS中,構造函數其實就可以看成類,對某個對象的抽象定義。
9 * @param {Object} name
10 * @param {Object} age
11 */
12 function Person(name, age){
13 //屬性:每個對象的屬性各不相同
14 this.name = name;
15 this.age = age;
16 }
17 //在原型上添加方法,這樣創建的所有對象都是用的同一套方法
18 Person.prototype.showName = function(){
19 alert("姓名:"+this.name);
20 }
21 Person.prototype.showAge = function(){
22 alert("年齡:"+this.age);
23 }
24
25 //創建兩個對象
26 var p1 = new Person("jiangzhou", 22);
27 var p2 = new Person("Lyli", 20);
28
29 alert(p1.showName == p2.showName); //true
30 //這裏爲什麼兩個對象的方法是相等的呢,可以看成如下
31 alert(p1.showName == Person.prototype.showName); //true
32
33 </script>
34 </head>
35 </html>
通過prototype我們還可以很方便的擴展系統對象,按照自己的需求來擴展,而且又能適用於所有地方,又不會浪費資源。如下面對Array進行擴展,求數組和的方法。
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="UTF-8">
5 </head>
6 <script>
7 /**
8 * 對數組原型擴展一個求和的方法;
9 * 注意不能只加在某個數組對象上,那樣的話只能在那個對象上適用。
10 */
11 Array.prototype.sum = function(){
12 var sum = 0;
13 for(var i=0;i<this.length;i++){
14 sum += this[i];
15 }
16 return sum;
17 }
18 //通過new Array() 和 [] 創建數組完全是一樣的效果。
19 var arr1 = new Array(1,2,3,4,5,6);
20 var arr2 = [11,22,33,44,55];
21
22 alert(arr1.sum());
23 alert(arr2.sum());
24
25 alert(arr1.sum == arr2.sum); //true
26 alert(arr2.sum == Array.prototype.sum); //true
27 </script>
28 </html>
最後註明:非原創,轉載學習!原文:地址