1. 程式人生 > >JS面向對象(封裝,繼承)

JS面向對象(封裝,繼承)

通過 ray 混合 字母 顯示 彈出 pan rip http

在六月份找工作中,被問的最多的問題就是: js面向對象,繼承,封裝,原型鏈這些,你了解多少?

額,,,我怎麽回答呢, 只能說,了解一些,不多不少,哈哈哈哈,當然,這是玩笑話。

不過之前學過java,來理解這些還是很容易的。

所以趁著自己空閑的時間,理一理,,這些,,

一、封裝

1.原始方法

 1 // 通過new關鍵字生成一個對象,然後根據javascript是動態語言的特性來添加屬性和方法,構造一個對象。其中this表示調用該方法的對象。
 2     var obj = new Object();
 3     obj.name = ‘jessie‘;
 4     obj.age = 22;
5 obj.showName = function(){ 6 alert(this.name); 7 }; 8 obj.showAge = function(){ 9 alert(this.age); 10 } 11 obj.showName(); //jessie 12 obj.showAge(); // 22 13 // 這種方式的問題是如果需要多次創建對象,那麽需要重復代碼多次,不利於代碼的復用。

2.工廠模式

 1 function createBlog(name, url) {
 2         var
obj = new Object(); 3 obj.name = name; 4 obj.url = url; 5 obj.sayName = function(){ 6 alert(this.name); 7 }; 8 obj.sayUrl = function() { 9 alert(this.url); 10 }; 11 return obj; 12 } 13 var blog1 = createBlog(‘jessie‘, ‘http://www.cnblogs.com/xiayu25/‘);
14 var blog2 = createBlog(‘cuit‘, ‘http://www.cuit.edu.cn‘); 15 blog1.sayName(); // jessie 16 blog1.sayUrl(); // http://www.cnblogs.com/xiayu25/ 17 blog2.sayName(); // cuit 18 blog2.sayUrl(); // http://www.cuit.edu.cn 19 20 // 通過定義幾個函數的對象,解決了不同對象持有函數對象的私有屬性問題。 21 // 現在所有對象的方法都持有上面兩個函數的引用, 22 // 但這麽一來,對象的函數又和對象相互獨立了,這和面向對象中持有方法屬於與特定類的思想不符。 23 // 可以看到工廠模式的實現方法非常簡單,解決了創建多個相似對象的問題, 24 // 但是工廠模式卻無從識別對象的類型,因為全部都是Object,不像Date、Array等,因此出現了構造函數模式。

3.構造函數模式

 1 function Blog(name, url){
 2         //var this=new Object();  //系統模擬創建對象
 3         this.name = name;
 4         this.url = url;
 5         this.sayName = function(){
 6             alert(this.name);
 7         };
 8         this.sayUrl = function(){
 9             alert(this.url);
10         };
11     }
12     var blog1 = Blog(‘jessie‘, ‘http://www.cnblogs.com/xiayu25/‘);
13     var blog2 = Blog(‘cuit‘, ‘http://www.cuit.edu.cn‘);
14     blog1.sayName(); // jessie
15     blog1.sayUrl(); // http://www.cnblogs.com/xiayu25/
16     blog2.sayName(); // cuit
17     blog2.sayUrl(); // http://www.cuit.edu.cn
18     // 這個例子與工廠模式中除了函數名不同以外,細心的童鞋應該發現許多不同之處:
19     // 函數名首寫字母為大寫(雖然標準沒有嚴格規定首寫字母為大寫,但按照慣例,構造函數的首寫字母用大寫)
20     // 沒有顯示的創建對象
21     // 直接將屬性和方法賦值給了this對象
22     // 沒有return語句
23     // 使用new創建對象
24     // 能夠識別對象(這正是構造函數模式勝於工廠模式的地方)
25     // 構造函數雖然好用,但也並非沒有缺點
26     // 構造函數的方式與工廠加工方式一樣,會為每個對象創建獨享的函數對象,
27     // 當然也可以將這些函數對象定義在構造函數外面,這樣又有了對象和方法相互獨立的問題

4.原型模式

 1 function Blog() {}
 2     Blog.prototype.name = ‘jessie‘;
 3     Blog.prototype.url = ‘http://www.cnblogs.com/xiayu25/‘;
 4     Blog.prototype.friend = [‘fr1‘, ‘fr2‘, ‘fr3‘, ‘fr4‘];
 5     Blog.prototype.alertInfo = function() {
 6         alert(this.name + this.url + this.friend );
 7     };
 8     
 9     var blog1 = new Blog(), blog2 = new Blog();
10     blog1.alertInfo();  // jessiehttp://www.cnblogs.com/xiayu25/fr1,fr2,fr3,fr4
11     blog2.alertInfo();  // jessiehttp://www.cnblogs.com/xiayu25/fr1,fr2,fr3,fr4
12     blog1.name = ‘test1‘;
13     blog1.url = ‘http://***.com‘;
14     blog1.friend.pop();
15     blog2.name = ‘test2‘;
16     blog2.url = ‘http://+++.com‘;
17     blog1.alertInfo();  // test1http://***.comfr1,fr2,fr3
18     blog2.alertInfo();  // test2http://+++.comfr1,fr2,fr3
19     // 上面的代碼通過blog1向blog1的屬性friend添加元素時,
20     // blog2的friend屬性的元素也跟著受影響,原因是在於blog1和blog2對象的friend屬性引用的是同一個Array
21     // 對象,那麽改變這個Array對象,另一個引用Array對象的屬性自然也會受到影響

5.混合模式(原型模式 + 構造函數模式)

 1 function Blog(name, url, friend) {
 2         this.name = name;
 3         this.url = url;
 4         this.friend = friend;
 5     }
 6 
 7     Blog.prototype.alertInfo = function() {
 8         alert(this.name + this.url + this.friend);
 9     };
10 
11     var blog1 = new Blog(‘jessie‘, ‘http://www.cnblogs.com/xiayu25/‘, [‘fr1‘, ‘fr2‘, ‘fr3‘]),
12             blog2 = new Blog(‘cuit‘, ‘http://www.cuit.edu.cn‘, [‘a‘, ‘b‘]);
13 
14     blog1.friend.pop();
15     blog1.alertInfo();  // jessiehttp://www.cnblogs.com/xiayu25/fr1,fr2
16     blog2.alertInfo();  // cuithttp://www.cuit.edu.cna,b
17 
18     //屬性私有後,改變各自的屬性不會影響別的對象。
19     // 同時,方法也是由各個對象共享的。在語義上,這符合了面向對象編程的要求。

6.動態原型模式

動態原型模式將所有信息封裝在了構造函數中,而通過構造函數中初始化原型(僅第一個對象實例化時初始化原型),這個可以通過判斷該方法是否有效而選擇是否需要初始化原型。

 1 function Blog(name, url) {
 2         this.name = name;
 3         this.url = url;
 4 
 5         if (typeof this.alertInfo != ‘function‘) {
 6             // 這段代碼只執行了一次
 7             alert(‘exe time‘);
 8             Blog.prototype.alertInfo = function() {
 9                 alert(thia.name + this.url);
10             }
11         }
12     }
13 
14     var blog1 = new Blog(‘jessie‘, ‘http://www.cnblogs.com/xiayu25/‘),
15             blog2 = new Blog(‘cuit‘, ‘http://www.cuit.edu.cn‘);
16     // 可以看到上面的例子中只彈出一次窗,‘exe time‘,即當blog1初始化時,
17     // 這樣做blog2就不在需要初始化原型,對於使用這種模式創建對象,可以算是perfect了。

二、繼承(主要是方法的繼承和屬性的繼承)

 1 function person(name, sex){
 2         this.name=name;
 3         this.sex=sex;
 4     }
 5     person.prototype.showName=function(){
 6         alert(this.name);
 7     };
 8     person.prototype.showSex=function(){
 9         alert(this.sex);
10     };
11 
12     function worker(name,sex,job){
13         person.call(this,name,sex);//構造函數偽裝   調用父級的構造函數--為了繼承屬性
14         this.job=job;
15     }
16     //原型鏈  通過原型來繼承父級的方法
17     for(attr in person.prototype){
18         worker.prototype[attr]=person.prototype[attr];
19     }
20     worker.prototype.showJob=function(){
21         alert(this.job);
22     };
23 
24     var op=new person(‘blue‘,‘女‘);
25     var ow=new worker(‘blue‘,‘女‘,‘程序員‘);
26     op.showName();  //blue
27     op.showSex();  //
28     ow.showName();  //blue
29     ow.showSex();  //
30     ow.showJob();  //程序員
31 
32     //繼承的好處:父類新加的功能,子類也具備該功能,子類新加的功能不會影響父類的功能

JS面向對象(封裝,繼承)