面向對象(OOP)--OOP基礎與this指向詳解

  前  言編程

          

 學過程序語言的都知道,咱們的程序語言進化是從「面向機器」、到「面向過程」、再到「面向對象」一步步的發展而來。相似於彙編語言這樣的面向機器的語言,隨着時代的發展已經逐漸淘汰;而面向過程的語言也只有C語言老大哥依然堅挺;如今主流的語言(例如Java、C++、PHP等)都是面向對象的語言。 而咱們的JavaScript語言,偏偏介於面向過程與面向對象之間,咱們稱它爲「基於對象」的語言。可是,JS中的OOP依然是咱們學習JS的重要一環,固然像「繼承」「封裝」這樣的面向對象特徵,都是由模擬實現的。今天,咱們就一塊兒來探討一下JS中的面向對象吧!數組

 


1、OOP基礎知識


1類和對象

面向對象編程(OOP)  思惟導圖函數

 

 

一、類:學習

    一類具備相同的特徵(屬性)和行爲(方法)的集合。
      eg:人類--> 屬性:身高、性別; 方法:吃飯、說話
二、對象:this

    從類中拿出具備肯定屬性值和方法的個體。
      eg:張三--> 屬性:身高:170、 體重;50kg; 方法: 說話-->我叫張三,身高170

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

四、使用類和對象的步驟:
  ① 建立一個類(構造函數):類名必須使用大駝峯法則。即,每一個單詞的首字母都要大寫,spa

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

 


  ② 經過類,實例化(new)出一個對象:code

var obj = new 類名(屬性值);
obj.屬性;    //調用屬性
obj.方法(); //調用方法



  ③ 注意事項:
       一、經過類名,new出一個對象的過程,叫作"類的實例化";

         二、類中的this,會在實例化的時候指向新new出的對象。
          因此,this.屬性、 this.方法 其實是將屬性和方法綁定在即將new出的對象上面;

       三、在類中,要調用自身的屬性,必須使用this.屬性。若是,直接使用變量名,則沒法訪問對象的屬性。

       四、類名必須使用大駝峯法則,注意與普通函數的分。
五、兩個重要屬性
    ① constructor :返回當前 對象 的構造函數。
     對象

 zhangsan.constructor == Person; √

 


    ② instanceof :檢測一個對象是否是一個類的實例;blog

lisi instanceof Person          √ lisi是經過Person類new出的
lisi instanceof Object           √ 全部對象都是Object的實例
Person instanceof Object     √ 函數自己也是對象

 



六、廣義對象與狹義對象:
  ① 狹義對象:只有屬性和方法,除此以外沒有任何其餘內容;繼承

var obj = {};
var obj = new Object();




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

var s = "12"; //不是對象
s.name = "aaa";
console.log(typeof(s)); //string
console.log(s.name);    // undefined 字面量聲明的字符串不是對象,不能添加屬性

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

 

 

2OOP的屬性和方法

 

成員屬性和成員方法

 

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

 

私有屬性和私有方法

二、經過"類名.屬性名"、"類名.方法名"申明的屬性和方法,稱爲靜態屬性、靜態方法 。也叫類屬性和類方法;
    類屬性/類方法,是屬於類的(屬於構造函數)。
    經過"類名.屬性名"調用
三、成員屬性是屬於實例化出的對象的,只能使用對象調用;
    靜態屬性是屬於構造函數的,只能使用類名調用。

 

私有屬性和私有方法

 

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

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

 

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

 

 

 
代碼解釋
 

 

function Person(name){
                this.name = name;                //聲明成員屬性
                var sex = "男";             //私有屬性
                this.sayTime =  function(){      //聲明成員方法
                    alert("我說當前時間爲"+getTime());
                }
                this.writTime =  function(){
                    alert("我寫了當前時間爲"+getTime());  //調用私有方法
                }               
                function getTime(){                //私有方法
                    return new Date;
                }
       }
  /***************************成員屬性/方法*************************/ var zhangsan = new Person("張三");      //類的實例化 zhangsan .age = 18;      //追加成員屬性 alert(zhangsan .name);    //調用成員屬性 /***************************靜態屬性/方法***************************/ Person.count = "60億"; //聲明靜態屬性 alert(Person.count); //調用靜態屬性 var lisi = new Person("李四"); alert(lisi.count); //undefined 靜態屬性是屬於類的,只能用類名調用 /*************************私有屬性/方法**************/ lisi.sayTime(); //外部間接調用 lisi.writTime();

 

 


2  this指向詳解

 

一、相關知識:

對於判斷this的指向問題,總的來講,就是:誰最終調用函數,this就指向誰。


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

二、雖然知道了,誰最終調用函數,this就指向誰。可是,仍是以爲有點籠統,不夠詳細。對this的指向問題仍是太模糊。

因而,在這裏,影子特向你們介紹,this指向問題規律的5條通用判斷方法。

  ① 經過 函數名() 調用的,this永遠指向window;
  ② 經過 對象.方法 調用的,this指向該對象;
  ③ 函數做爲 數組 中的一個元素,用數組下標調用的,this指向該數組;
  ④ 函數做爲Window內置函數的 回調函數 使用,this指向window;
    setInterval、 setTimeout
  ⑤ 函數做爲構造函數,使用 new關鍵字 調用,this指向新new出的對象。

 

下面,將對每條規律,作出案例,以供你們,理解:

<div id="div1"style="width: 200px;height: 200px;background-color: red;">
            這是一個div
</div>

 

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

 

下面是一個影子總結的一個綜合案例:

        /************************綜合案例****************/
        var obj1 = {
            name : "obj1",
            arr : [func, 1,{name : "obj2",func : func},3,4],
        }
        obj1.arr[0]();                        //最終的調用者是數組,this指向數組
        setTimeout(obj1.arr[0],1000);        //obj1.arr[0僅僅是取到函數func,但並無調用。函數的最終調用者是setTimeout,指向window;這個式子至關於setTimeout(func,1000);
        setTimeout(obj1.arr[2].func,1000);    //函數的最終調用者是setTimeout.緣由同上↑
        obj1.arr[2].func();                    //最終的調用者是{name : obj2,func : func},this指向{name : obj2,func : func}
        

 

好了,今天影子給你們分享的東西就這麼多了。最後,影子這裏還有一道this指向的題,就一這道題結束今天的分享吧。至於答案就留到下次。哈哈。。。

var fullname = 'John Doe';
        var obj = {
           fullname: 'Colin Ihrig',
           prop: {
              fullname: 'Aurelio De Rosa',
              getFullname: function() {
                 return this.fullname;
              }
           }
        };
       console.log(obj.prop.getFullname());          //??
        var test = obj.prop.getFullname;
        console.log(test());  
        //??
        obj.func = obj.prop.getFullname;
        console.log(obj.func());             //???
        var arr = [obj.prop.getFullname,1,2];
        arr.fullname = "JiangHao";      
        console.log(arr[0]());              
        console.log(arr[0]);        //????         
相關文章
相關標籤/搜索