JavaScript面向對象(OOP)

  前  言javascript

JRedujava

       面向對象程序設計(簡稱OOP)是如今最流行的程序設計方法,這種方法有別於基於過程的程序設計方法。在寫面向對象的WEB應用程序方面JavaScript是一種很好的選擇.它能支持OOP.由於它經過原型支持繼承的方式和經過屬性和方法的方式同樣好.不少開發者試圖拋棄JS,試着用C#或JAVA僅是由於JS不是他認爲合適的面向對象的語言.許多人尚未認識到javascript支持繼承.當你寫面向對象的代碼時.它能給你很強大的能量.你也可使用它寫出可複用,可封裝的代碼.面試

 

1、什麼是面向對象編程(OOP)?

        在瞭解什麼是面向對象編程以前,咱們來看看語言的分類。整體能夠分爲三類:面向機器面向過程還有面向對象。面向對象的語言主要有C++、Java、PHP等。編程

1面向過程與面向對象    

1)面向過程:面向過程專一於如何去解決一個問題的過程步驟。編程特色是由一個個函數去實現每一步的過程步驟,沒有類和對象的概念。
2)面向對象:專一於由哪個對象來解決這個問題,編程特色是出現了一個類,從類中拿到對象,由這個對象去解決具體問題。
         對於調用者來講,面向過程須要調用者本身去實現各類函數。而面向對象,只須要告訴調用者,對象中具體方法的功能,而不須要調用者瞭解方法中的實現細節。數組

2面向對象的三大特徵

      這個對於計算機專業的人來講,相信你們已經很熟悉啦,那我就再說一遍吧~函數

      面向對象的三大特徵是繼承、封裝、多態。JS能夠模擬實現繼承和封裝,可是沒法模擬實現多態,因此咱們說JS是一門基於對象的語言,而非是面向對象的語言。this

3類和對象

 

一、類:一類具備相同特徵(屬性)和行爲(方法)的集合。
好比,人類具備身高、體重等屬性,吃飯、大笑等行爲,因此,咱們能夠把人劃分爲一類。spa


二、對象:從類中,拿出具備肯定屬性值和方法的個體。
好比,張三-->屬性:身高180體重180 方法:說話-->我叫張三,身高180

三、類和對象的關係:
①類是抽象的,對象是具體的(類是對象的抽象化,對象是類的具體化)

②類是一個抽象的概念,只能說類有屬性和方法,可是不能給屬性賦具體的。好比,人類有姓名,可是不能說人類的姓名叫什麼。
   對象是一個具體的個例,是將類中的屬性進行具體賦值而來的個體。
好比,張三是一我的類的個體。能夠說張三的姓名叫張三。也就是張三對人類的每個屬性進行了具體的賦值,那麼張三就是由人類產生的一個對象。

四、使用類和對象的步驟:設計

1)建立一個類(構造函數):類名必須使用大駝峯法則。即每一個單詞首字母都要大寫code

function 類名(屬性1){
     this.屬性1=屬性1;
     this.方法=function(){
      //方法中要調用自身屬性,必須使用this.屬性
     }
}

2)經過類實例化(new)出一個對象。

var obj=new 類名(屬性1的具體值);
obj.屬性; 調用屬性
obj.方法; 調用方法

3)注意事項
①經過類名,new出一個對象的過程,叫作"類的實例化"。
②類中的this,會在實例化的時候,指向新new出的對象。
因此,this.屬性 this.方法其實是將屬性和方法綁定在即將new出的對象上面。
③在類中,要調用自身屬性,必須使用this.屬性名。若是直接使用變量名,則沒法訪問對應的屬性。

function Person(name,age){
   this.name=name;
   this.age=age;
   this.say=function(content){
       //在類中,訪問類自身的屬性,必須使用this.屬性調用。
       alert("我叫"+this.name+",今年"+this.age+"歲,我說了一句話:"+content);
   }
}
var zhangsan=new Person("姐姐",18);
zhangsan.say("你好呀");

④類名必須使用大駝峯法則,注意與普通函數區分。

4面向對象的兩個重要屬性

1)constructor:返回當前對象的構造函數。
>>>zhangsan.constructor==Person;  ( true)
2)instanceof:檢測一個對象是否是一個類的實例;
>>>lisi instanceof Person              √ lisi是經過Person類new出的
>>>lisi instanceof Object              √ 全部對象都是Object的實例
>>>Person instanceof Object        √ 函數自己也是對象

5廣義對象與狹義對象

1)狹義對象:只有屬性和方法,除此以外沒有任何其餘內容。

 

var obj={};  //用{}聲明的對象
var obj=new Object(); //用new聲明的對象

 

2)廣義對象:除了用字面量聲明的基本數據類型以外,JS中萬物皆對象。換句話說,只要能添加屬性和方法的變量,均可以稱爲對象。

var s="123";  //不是對象
s.name="aaa";
console.log(typeof(s)); //String
console.log(s.name); //undfined 字面量聲明的字符串不是對象,不能添加屬性
var s=new String("123");  //是對象
s.name="aaa";
console.log(typeof(s)); //Object
console.log(s.name); //"aaa" 使用new聲明的字符串是對象,能添加屬性和方法。

 

2、 成員屬性、靜態屬性和私有屬性

一、在構造函數中,使用this.屬性聲明。或者在實例化出對象之後,使用"對象.屬性"追加的,都屬於成員屬性成員方法。也叫實例屬性或實例方法。
     成員屬性/方法,是屬於由類new出的對象的。
     須要使用"對象名.屬性名"調用。

【靜態屬性與靜態方法】
二、經過「類名.屬性名」、「類名.方法名」聲明的屬性和方法,稱爲靜態屬性靜態方法。也叫類屬性和類方法。
     類屬性/類方法,是屬於類的(屬於構造函數的)
     經過"類名.屬性名"調用。

三、成員屬性是屬於實例化出的對象的,只能使用對象調用。
靜態屬性是屬於構造函數的,只能使用類名調用。

[私有屬性和私有方法]
四、在構造函數中,使用var聲明的變量稱爲私有屬性;
在構造函數中,使用function聲明的函數,稱爲私有方法;

function Person(){
    var num=1;//私有屬性
    function func(){}//私有方法
}

私有屬性和私有方法的做用域,只在構造函數內容有效。即只能在構造函數內部使用,在構造函數外部,不管使用對象名仍是類名都沒法調用。

 

function Person(name){
    this.name=name; //聲明成員屬性
    var sex="男";//私有屬性
                
}
            
var zhangsan=new Person("張三");
zhangsan.age=14; //追加成員屬性
alert(zhangsan.name); //調用成員屬性
            
Person.count="60億"; //聲明靜態屬性
alert(Person.count); //調用靜態屬性
var lisi=new Person("李四");
console.log(lisi.count);
//undefined 靜態屬性是屬於類的,只能用類名調用。

 

3、 JavaScript模擬實現封裝

一、什麼叫封裝?
①方法的封裝:將類內部的函數進行私有化處理,不對外提供接口,沒法在類外部使用的方法,稱爲私有方法,即方法的封裝。
②屬性的封裝:將類中的屬性進行私有化處理,對外不能直接使用對象名訪問(私有屬性)。同時,須要提供專門用於設置和讀取私有屬性的set/get方法,讓外部使用咱們提供的方法,對屬性進行操做。這就叫屬性的封裝。
二、注意:封裝不是拒絕訪問,而是限制訪問。要求調用者,必須使用咱們提供的set/get方法進行屬性的操做,而不是直接拒絕操做。
所以,單純的屬性私有化,不能稱爲封裝!必需要有私有化後,提供對應的set/get方法。

function Person(name,age1){
    this.name=name;
// this.age=age; var age=0; this.setAge=function(ages){ if(ages>0&&ages<=120){ age=ages; }else{ alert("年齡賦值失敗"); } } // 當實例化類拿到對象時,能夠直接經過類名的()傳入年齡,設置私有屬性 if(age1!=undefined) this.setAge(age1); this.getAge=function(){ return age; } this.sayTime=function(){ alert("我說當前時間是:"+getTime()); } this.writeTime=function(){ alert("我寫了當前時間是:"+getTime()); }
/*私有化的方法,只能在類內部被其餘方法調用,而不能對外提供功能。這就是方法的封裝*/ function getTime(){ return new Date(); } } var zhangsan=new Person("張三",99); zhangsan.setAge(99); alert("張三的年齡是"+zhangsan.getAge()); var lisi=new Person("李四",99); lisi.setAge(110); alert("李四的年齡是:"+lisi.getAge());

 

4、JavaScript中的this指向詳解

一、誰最終調用函數,this最終指向誰(記住!)
①this指向誰,不該考慮函數在哪聲明,而應該考慮函數在哪調用!!!
②this指向的永遠只多是對象,而不多是函數。
③this指向的對象,叫作函數的上下文context,也叫函數的調用者。


二、this指向的規律!!!(跟函數的調用方式息息相關,記住這點,相信你必定會分清this指向噠)
①經過函數名()調用的,this永遠指向window
②經過對象.方法調用的,this指向這個對象。
③函數做爲數組中的一個元素,用數組下標調用的,this指向這個數組
④函數做爲window內置函數的回調函數使用,this指向window。
setInterval setTimeout 等。
⑤函數做爲構造函數,使用new關鍵字調用,this指向新new出的對象。

function func(){
    console.log(this);
}
var obj={
    name:"zhangsan",
    func:func
}
//①經過函數名()調用的,this永遠指向window。
func();
//②經過對象.方法調用的,this指向這個對象
obj.func();//狹義對象
            
window.onclick=function(){
    document.getElementById("div1").onclick=function(){
        func();//最終仍是使用()調用,因此指向window
    }
    document.getElementById("div1").onclick=func;//廣義對象,指向div
}
//③函數做爲數組中的一個元素,用數組下標調用的,this指向這個數組
var arr=[1,2,3,func,4,5,6];
arr[3]();
            
//④函數做爲window內置函數的回調函數使用,this指向window。
setTimeout(func,1000);
            
//⑤函數做爲構造函數,使用new關鍵字調用,this指向新new出的對象。
var obj1=new func();

如今,你必定分清了this指向了吧,下面咱們來看一個綜合案例:

var obj1={
    name:"obj1",
    arr:[func,1,{name:"obj2",func:func},3,4],
}
obj1.arr[0]();//最終的調用者是數組。this-->obj.arr
setTimeout(obj1,arr[0],2000);//obj.arr[0]僅僅是取到函數賦給setTimeout,但並無調用。函數的最終調用者是setTimeout。這個式子至關於setTimeout(func,2000);
obj1.arr[2].func();//最終調用者是{name:"obj2",func:func}
setTimeout(obj1.arr[2].func,2000);//最終調用者是setTimeout
            
//↓最終的調用者是div1
//document.getElementById("div1").onclick=obj1.arr[0]; //document.getElementById("div1").onclick=arr[2].func;

最後,咱們再來看一道面試題:

var fullname = 'John Doe';
var obj = {
   fullname: 'Colin Ihrig',
   prop: {
      fullname: 'Aurelio De Rosa',
      getFullname: function() {
         return this.fullname;
      }
   }
};
console.log(obj.prop.getFullname()); 
// 函數的最終調用者 obj.prop 
            
var test = obj.prop.getFullname;
console.log(test());  
// 函數的最終調用者 test()  this-> window
            
obj.func = obj.prop.getFullname;
console.log(obj.func()); 
// 函數最終調用者是obj
            
var arr = [obj.prop.getFullname,1,2];
arr.fullname = "JiangHao";
console.log(arr[0]());
// 函數最終調用者數組

此次就分享到這了,下次再介紹JS中OOP中的繼承方法吧~

相關文章
相關標籤/搜索