javascript面向對象編程筆記

對象:一切事物皆是對象。對象是一個總體,對外提供一些操做。好比說一個收音機是一個對象,咱們不須要知道它的內部結構是什麼,只須要會使用外部的按鈕就可使用收音機。javascript

 

面向對象:面嚮對象語言的標誌是他們都有類的概念,經過類能夠建立任意多個具備相同屬性的方法的對象。任何對象都是某一類事物的實例,簡單的說就是使用對象時,只關注對象提供的功能,不關注其內部細節。java

 

面向對象的特色:封裝,繼承,多態。安全

 

JS中面向對象的組成:1.方法(函數):過程,動態的 2.屬性(有所屬關係的變量):狀態,靜態的函數

 

對象是無序屬性的集合,其屬性能夠包括基本值、函數、對象。每一個屬性都會有一個名字,每一個名字映射到一個值上
下面是建立一個對象的一些方法this

1.工廠模式編碼

 1 function createPerson (name,sex) {//工廠方式構造一個對象
 2 
 3         //1.原料 
 4         var obj=new Object(); //new一個空白對象
 5         
 6         //2.加工
 7         obj.name=name;
 8         obj.sex=sex;
 9 
10         obj.showName=function(){
11             console.log('個人名字叫:'+this.name)
12         }
13 
14         obj.showSex=function(){
15             console.log('我是:'+this.sex+'的')
16         }
17         
18         //3.出廠
19         return obj;//這一步千萬不能那下
20     }
21 
22     var p1=createPerson('木木','女');//每用一次createPerson 就會new一個對象,每一個對象都有一套本身的方法 形成資源浪費
23     var p2=createPerson('揚揚','男');
24 
25     p1.showName();
26     p1.showSex();
27     p2.showName();
28     p2.showSex();

使用工廠方式構造對象步驟:
1,原料
2.加工
3.出廠
工廠方式不經常使用,由於有缺點:1.沒有new 2.每一個對象都有一套本身的函數,形成資源的浪費
怎麼解決這個兩個問題呢?那麼請看下面spa

2.構造函數模式prototype

 1 function Person (name,sex) {//構造函數   構造一個對象
 2         this.name=name;//this:當前的方法屬於誰(在函數前面有new時會失效)
 3         this.sex=sex;
 4 
 5         this.showName=function(){
 6             console.log('個人名字叫:'+this.name);
 7         }
 8 
 9         this.showSex=function(){
10             console.log('我是:'+this.sex+'的');
11         }
12        
13     }
14 
15     var p1=new Person('木木','女');  //外面加new後Person函數裏面就不用new一個空白對象
16     var p2=new Person('揚揚','男');
17 
18     console.log(p1.showName==p2.showName);//fase
19 
20     p1.showName();
21     p1.showSex();
22     p2.showName();
23     p2.showSex();

注意:通常將Person稱爲構造函數,而且構造函數的名字首字母大寫,這是編碼規範。
this:表示當前的方法屬於誰,可是在這裏當this碰到New時就會失效。
用造函數模式解決了上面工廠模式沒有New的問題
這時就要想想了在使用new操做符調用構造函數建立一個新實例的過程當中發生了什麼呢?一個新實例是怎麼生成的呢?
這種方式調用構造函數經歷如下四個步驟:
1.建立一個新對象
2.將構造函數的做用域賦給新對象(所以this就指向了這個新對象)
3.執行構造函數中的代碼(爲這個新對象添加屬性)
4.返回新對象指針

1 function show(){
2         alert(this);
3     }
4     show();//彈出window對象(當在全局做用域中調用一個函數時,this對象總指向window對象,全局函數屬於window的一個方法)
5     new show();//彈出obj (this會指向)新建立的一個對象

面這個例子會看得更加清楚
做爲普通函數調用:code

 1 var name = "mumu";
 2         function Person(name){
 3             this.name = name;
 4             this.show = function(){
 5             console.log("我是" + this.name);
 6             }
 7         }
 8 
 9         Person("javascript");
10         console.log(name);//結果是javascript

全局變量name被修改了

做爲構造函數調用:

 1 var name = "mumu";
 2         function Person(name){
 3             this.name = name;
 4             this.show = function(){
 5             console.log("我是" + this.name);
 6             }
 7         }
 8 
 9         var Name = new Person("HTML");
10         console.log(Name.name);
11         console.log(name);

this指向新對象Name,全局變量name也沒有變化

那麼問題又來了:

1 console.log(p1.showName==p2.showName);//fase

不一樣實例的showName()函數是不相同的,那麼怎麼解決這個問題呢?下面是一個解決辦法

 1 function Person (name,sex) {//構造函數  
 2         this.name=name;//this:當前的方法屬於誰(在函數前面有new時會失效)
 3         this.sex=sex;
 4 
 5         this.showName=showName;
 6         
 7     }
 8     function showName(){
 9             console.log('個人名字叫:'+this.name+'我是:'+this.sex+'的');
10         }
11 
12     var p1=new Person('木木','女');  //外面加new後Person函數裏面就不用new一個空白對象
13     var p2=new Person('揚揚','男');
14 
15     console.log(p1.showName==p2.showName);//ture
16 
17     p1.showName();
18     p2.showName();

將showName定義成一個全局方法,這樣每一個實例共享的都是全局方法showName()。不相等的問題是解決了,但是若是構造函數裏有大量的方法,這就形成代碼中有大量的全局變量,這樣咱們自定義的引用類型就沒有封裝性了,資源仍是照樣浪費。那麼怎麼解決這個問題呢?請看原型模式

3.原型模式

 1 function Person(name,sex) {//原型模式構造函數   
 2         Person.prototype.name=name;
 3         Person.prototype.sex=sex;
 4         Person.prototype.showName=function(){
 5             console.log('個人名字叫:'+this.name+'我是:'+this.sex+'的');
 6         }
 7     }
 8 
 9     var p1=new Person('木木','女'); 
10     var p2=new Person('揚揚','男');
11 
12     console.log(p1.showName==p2.showName);//ture
13     
14     p1.showName();
15     p2.showName();

prototype(原型)返回對象類型原型的引用。這個屬性是一個指針,指向對象。可讓全部對象實例共享它所包含的屬性和方法,能夠擴展系統對象,節省系統資源,因此這裏解決了上面資源浪費問題。
原型的問題:是當一個實例改變屬性值時,全部實例對應的屬性值也都跟着改變,沒法初始化屬性值,當爲對象實例添加一個屬性時,這個屬性就會屏蔽原型對象中保存的同名屬性,下面是個小例子:

 1 function Person(name,sex) {//原型模式構造函數   
 2         Person.prototype.name=name;
 3         Person.prototype.sex=sex;
 4         Person.prototype.showName=function(){
 5             console.log('個人名字叫:'+this.name+'我是:'+this.sex+'的');
 6         }
 7     }
 8 
 9     var p1=new Person('木木','女'); 
10     var p2=new Person('揚揚','男');
11     
12     p1.name="兮兮";
13 
14     p1.showName();//兮兮 來自實例
15     p2.showName();//揚揚 來自原型

前面幾種方法都各有各優缺點,那麼把它們綜合一下又會怎麼樣呢?

4.組合使用構造函數模式和原型模式

 1 //構造函數模式定義實例屬性
 2     function Person (name,sex) {   
 3         this.name=name;
 4         this.sex=sex;
 5     }
 6     
 7     //原型模式共用方法和共享屬性
 8     Person.prototype.showName=function(){
 9             console.log('個人名字叫:'+this.name+'我是'+this.sex+'的')
10         }
11 
12     var p1=new Person('木木','女'); 
13 
14     p1.showName();

這種方法是最經常使用的,結合了兩種方法的優勢,最大限度地節省了內存

5.動態原型模式

 1 function Person(name, age) {
 2     this.name = name;
 3     this.age = age;
 4 
 5         //方法
 6         if(typeof this.showName != 'function') {
 7             Person.prototype.showname = function() {
 8                 console.log("個人名字是: " + this.name);
 9             }
10         }
11     }
12     var person1 = new Person("mumu", 17);
13     person1.showname();

動態原型方法能夠經過檢查方法是否有效,決定初始化的原型。這種方法堪稱爲完美,可是不能使用面向字面量重寫原型,這樣會切斷現有實例與新原型之間的聯繫。

6.寄生構造函數模式

 1 function createPerson(name, age) {
 2         var obj=new Object();
 3         obj.name = name;
 4         obj.age = age;
 5         obj.showName = function() {
 6             console.log("個人名字是:" + this.name);
 7         }
 8         return obj;
 9     }
10     var person = new createPerson("mumu", 17);
11     person.showName();

此方法能夠和工廠模式對比一下,建立實例方法與構造函數相同,其他與工廠模式相同。若是前面方法都不適用能夠考慮一下這種方法,可是這種方法構造函數返回的對象與實例沒有關係,也不能依賴instanceof判斷對象類型,所以,若是可使用其餘模式這種方法建議仍是不要使用。

7.穩妥構造函數模式

 1 function Person(name, age) {
 2         var obj = new Object();
 3         //定義一些私有變量和函數
 4         obj.showName = function() {
 5             console.log("個人名字是:" + name); //定義的私有變量等只能經過showName訪問
 6         }
 7         return obj;
 8     }
 9     var person1 = Person("兮兮", 17);
10     person1.showName();

所謂穩妥對象,指的是沒有公共屬性。這種方法適合用於在安全的環境下,由於它不使用new調用構造函數,也不使用this引用實例方法。若想訪問其屬性,只能經過showname方法來訪問其內部私有屬性。

相關文章
相關標籤/搜索