JS面向對象(一)——構造函數的封裝


基本概念

對象:對象就是一個整體,對外提供一個整體。

面向對象:使用對象時,只關注對象提供的功能,不關注其內部的細節。

三個特點(類C++):封裝、繼承、多態

一些概念區別

1、方法與函數

方法:obj.fn = function(){}

函數:function fn(){}

其中函數 function fn(){} 相當於 window.fn = function(){}

2、類與對象

類:不具備實際的功能,只能用來構造對象

對象:真正有功能的東西,被類給構造出來的

封裝構造函數(工廠模式)

以person為對象舉例 (有兩個屬性 name sex)

 1     <script>
 2         function CreatePerson(name , sex){
 3             var obj = new Object();
 4 
 5             //添加屬性
 6             obj.name = name;
 7             obj.sex = sex;
 8 
 9             //添加方法
10             obj.showName = function () {
11                 alert(this.name);
12             };
13             obj.showSex = function () {
14                 alert(this.sex);
15             };
16             return obj;
17         }
18 
19         var p1 = CreatePerson('leo' , 'male');
20         var p2 = CreatePerson('shawn' , 'male');
21         p1.showName();
22         p1.showSex();
23 
24         alert(p1.showName == p2.showName);
25     </script>
View Code

以這樣的方式(其實就是創建一個函數,然后實例對象利用函數傳參來實現,這樣做的話實例之間是沒有什么內在聯系的)來構造對象會有兩個問題:

1、沒有用到new方法

2、每個被創建的對象都有一套自己的方法(例如上述p1.showName()、p2.showName()),而這些方法的實現是一模一樣的,這樣就造成了資源的極度浪費

解決方案

針對第一個問題,做出的改進如下

 1         function CreatePerson(name , sex){
 2 
 3             //相當於這邊有
 4             // var this = new Object();
 5             //添加屬性
 6             this.name = name;
 7             this.sex = sex;
 8 
 9             //添加方法
10             this.showName = function () {
11                 alert(this.name);
12             };
13             this.showSex = function () {
14                 alert(this.sex);
15             };
16             //這邊有return this;
17         }
View Code

這個時候生成的實例對象會自動包含一個constructor屬性,指向它們的構造函數

當然還可以使用instanceof來驗證實例對象是否屬於原型對象

 

針對第二個問題,我們可以使用prototype(原型),Javascript規定,每一個構造函數都有一個prototype屬性,指向另一個對象。這個對象的所有屬性和方法,都會被構造函數的實例繼承。這意味着,我們可以把那些不變的屬性和方法,直接定義在prototype對象上。這很像CSS中的class,可以給一堆對象加上相同的屬性或方法。主要是用來添加一些系統不支持的方法或函數

 1    <script>
 2         function CreatePerson(name , sex){
 3             //添加屬性
 4             this.name = name;
 5             this.sex = sex;
 6         }
 7         //添加共用方法
 8         CreatePerson.prototype.showName = function () {
 9             alert(this.name);
10         };
11         CreatePerson.prototype.showSex = function () {
12             alert(this.sex);
13         };
14 
15         var p1 = new CreatePerson('leo' , 'male');
16         var p2 = new CreatePerson('shawn' , 'male');
17         p1.showName();
18         p1.showSex();
19 
20         alert(p1.showName == p2.showName);
21     </script>
View Code

這個時候我們會發現最后的輸出是true,這時候用的都是同一個內存地址,指向了prototype對象,內存的使用效率就變高。

 

最后關於一個優先級的問題

 

 1     <script>
 2         Array.prototype.a = 12;  //給Array類添加公共屬性a = 12;
 3         var arr = [1,2,3];
 4         alert(arr.a);  //12
 5 
 6         arr.a = 5;   //給由Array類所創造的對象arr添加重名屬性a
 7         alert(arr.a);  // 5
 8 
 9         delete  arr.a;  //刪除arr對象的a屬性
10         alert(arr.a);  //12
11     </script>
View Code

 

我們會發現這和CSS中內部樣式和行間樣式很相像,prototype添加的屬性相當於一個內部樣式 ,而對象的重名屬性相當於行間樣式 , 所以重名時對象的屬性優先級肯定是高於prototype所添加的屬性的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM