2-面向對象3大特性 創建對象的4種方式 構造函數注意點 構造函數的原型對象(使用方法/注意事項) 實例/實例化 實例/原型成員

面向對象的三大特性

  • 封裝: 在JS中使用對象封裝一些變量和函數
    • 好處: 信息隱蔽, 方便擴展維護, 提高代碼的復用性
  • 繼承: 一個類(對象)獲取另一個類(對象)的屬性和方法的一種形式
    • 面向對象語言定義: 是否有類的概念(c++ Java)
    • JS沒有類的概念, JS從這個角度說不是面向對象語言. 但面向對象具有繼承特性, 可以說JS支持面向對象語言
  • 多態: 同一操作, 作用于不同對象, 會產生不同行為(解釋)
    • 實現: JS天生就具有多態的特性(弱類型語言)

創建對象的方式

  1. 字面量的方式

     var student = {
         name: 'zs',
         age: 16,
         class: '一分鐘精通JS'
     }
     //一個班級有N個學生, 通過字面量形式, 需要創建N個學生對象
     //問題: 創建多個同類型的對象時, 大量代碼冗余(重復代碼)
     //價值: 只需要創建簡單的幾個對象
    
  2. 內置的構造函數

    • 系統內置的構造函數: Object | Array | Math | Date | Function | String | Number | Boolean

        var stu = new Object();
        stu.name= 'zs';
        stu.age= 16;
        stu.class=  '一分鐘精通JS';
        //跟字面量的方式差不多, 問題也是一樣-->創建對象的相同部分進行函數封裝(簡單工廠)
      
  3. 簡單的工廠方式: 類似函數封裝, 相同的不變, 不同的作為參數傳進來

     function person(){
         var stu = new Object();
         stu.name= 'zs';
         stu.age= 16;
         stu.class=  '一分鐘精通JS';
         //返回該對象
         return stu;
     }
     var stu1 = person();
     var stu2 = person();    
     //問題: 兩個學生信息都一樣
    
     //優化如下: 不同的信息當做參數傳進來                
     function person(name, age, classes){
         var stu = new Object();
         stu.name= name;
         stu.age= age;
         stu.class=  classes;
         return stu;
     }               
     function dog(name, age, classes){
         var dog = new Object();
         dog.name= name;
         dog.age= age;
         dog.class= classes;
         return dog;
     }
     var stu3 =  person('zs', 16, '一分鐘精通JS' );   
     var dog = dog('wangCai', 5 , '騎單車');
     console.log(stu3 == dog);    //false
     //問題: 創建不同類型的對象時, 無法分辨其類型       
    
  4. 自定義構造函數-參照上一章構造函數創建對象

    • 定義

      • 自己定義的構造函數(首字母大寫)-通過this設置屬性/方法-使用new調用構造函數創建對象
    • 執行過程

      1. 通過new關鍵字調用構造函數,構造函數內部默認創建一個新對象
      2. 將這個新對象賦值給this
      3. 通過this設置屬性和方法
      4. 默認返回新創建對象
    • 返回值

      • 如果沒有顯示return, 默認返回構造函數內部新創建的對象
      • 若寫了返回值, 要看具體情況
        • 如果返回值類型的數據, 就直接忽略, 返回內部新創建的對象
        • 若返回引用類型的數據, 直接返回該數據(會覆蓋內部新創建的對象)
    • 自定義構造函數(區別于簡單的工廠函數)

      1. 函數名首字母大寫
      2. 自定義構造函數內部會默認創建一個對象-默認將這個對象賦值給this
      3. 默認會返回新創建的對象
      4. 創建不同類型的對象時, 可以分辨其類型

構造函數注意事項

  1. 函數傳值: 函數當做參數傳進構造函數
  2. 判斷對象的類型
    • 對象 instanceof 構造函數: 判斷指定對象是否由某個構造函數創建出來
  3. 獲取對象類型: 構造器屬性obj.constructor
  4. 構造函數調用-區別于函數調用
    • new關鍵字: 默認創建/返回對象

    • 構造函數: 對這個對象進行一些初始化的操作(將創建對象賦值給this, 通過this綁定屬性/方法)

         function Person(name) {
              // this = obj;
      
              console.log(this);
              this.name = name;
              // return obj;
         }
        var p1 = new Person('zs');
      
        // 構造函數也是一個函數
        var p2 = Person('ls'); // 可以這樣寫,但是不建議這樣做
        console.log(p2); // undefined, 直接調用構造函數,this指向window
      
       //分析打印結果
       <script>
            function fn(){
                var t = 1;
                this.x = 3;
                document.write(t);
                document.write(this.x);
            }
            var obj = new fn();
            document.write(obj.x);
            document.write(fn());
        </script>
      

構造函數的原型對象

  1. 原型對象定義

    • 在構造函數創建出來時, 系統默認會創建一個對象與這個構造函數相關聯, 這個對象稱為該構造函數的原型對象


      構造函數的原型對象
  2. 作用

    • 使用構造函數創建出來的對象, 默認就可以使用該構造函數原型對象的屬性和方法
  3. 訪問原型對象: 構造函數.prototype

  4. 設置原型對象: 構造函數.prototype.name = 'name1';

    • 原型對象本質也是一個對象, 可以利用對象的動態特性設置原型對象
  5. 約定

    • 該對象構造函數的原型對象
    • 構造函數的原型對象(原型) | 對象的原型對象(原型)

實例與實例化

  • 實例: 通過構造函數創建出來的對象.
    • 一般說: XX是構造函數的實例
    • 實例成員: 實例屬性+實例方法
  • 實例化: 通過構造函數創建對象的過程
  • 注意點
    • 實例對象可以訪問實例成員和原型成員, 但是不能夠訪問靜態成員
    • 構造函數在訪問靜態方法時, 內部的this指向的是構造函數自己, 不能訪問到實例對象的成員
    function Person() {
        this.name = "張三";   //實例屬性
        var age = 18;       //私有變量
        this.showName = function () {       //實例方法
            console.log(this.name);
        }
        this.showAge = function () {    //特權方法
            console.log(age);   
        }
    }   
    Person.prototype.show = function () {   //原型方法
        console.log(this.name);
    }   
    Person.des = function () {  //靜態方法
        console.log(this.name);
    }   
    var p1 = new Person();

    p1.showName();  //張三
    p1.showAge();   //18
    p1.show();      //張三
    //p1.des();       //undefined ? 報錯(Y)
    Person.des();     //undefined ? 報錯 ? 張三 ?Person(Y)

原型的使用方法

  • 利用對象的動態特性設置原型對象
    • 提供一個構造函數
    • 設置原型對象的成員(原型屬性+原型方法)
      • 添加成員: 構造函數.prototype.name = "name1";
      • 修改成員: 構造函數.prototype.name = "name2";
      • 刪除成員: delete 構造函數.prototype.name;
  • 替換原型對象: 自己定義的對象賦值給原型對象
    1. 替換原型對象之前創建的對象和替換之后創建的對象,他們的原型對象不是同一個對象
    * 注意點: 獲取替換原型對象的屬性與替換之前原型對象的屬性值不相等
    * 建議: 最好在替換原型對象之后, 再創建對象
    
    1. 修正構造器屬性

使用原型對象的注意事項

  • 訪問原型對象的屬性-方式
    1. 對象.屬性(就近原則)
      • 首先查找自身是否有該屬性, 若有就直接使用
      • 若沒有就查找該對象原型對象的屬性, 若有就直接使用
      • 再沒有就返回undefined或報錯
    2. 構造函數.prototype.屬性
  • 設置原型對象
    • 通過對象.屬性設置屬性
      • 如果有這個屬性就是修改, 沒有這個屬性就是添加屬性, 不會修改原型對象的屬性
    • 設置原型對象的屬性
      • 通過構造函數.prototype.屬性或者替換原型
      • 如果原型屬性是引用類型的數據, 可以通過對象.屬性.屬性的方式修改

構造器屬性相關

  • constructor屬性: 指向與之對應的構造函數
  • 對象.constructor: 訪問的是原型對象的constructor屬性

__proto__屬性

  • 定義
    • 構造函數創建出來的對象, 默認就有一個__proto__屬性, 該屬性指向該對象對應的構造函數的原型對象
  • 訪問原型對象-方式
    1. 構造函數.prototype
    2. 對象.__proto__
      • 注意點: 在正式開發中, 不建議使用. 該屬性不是ES標準, 是部分瀏覽器廠商方便調試程序


        __proto__和constructor結構關系圖

hasOwnProperty()

  • 語法: 對象.hasOwnProperty("屬性名")
  • 定義: 判斷對象中是否存在指定的屬性(實例屬性)/ES5 中判斷對象的自有屬性(hasOwnProperty)
  • in區別: in判斷對象中是否存在指定的屬性(不區分實例屬性/原型屬性)

isPrototypeOf()

  • 語法: 構造函數.protoType.isPrototypeOf(對象)
  • 定義: 判斷一個對象是否是指定對象的原型對象(判斷原型對象是否在整條原型鏈上)
  • instanceof區別: instanceof判斷一個對象是否是指定構造函數的實例對象
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,908評論 2 372

推薦閱讀更多精彩內容