2-面向?qū)ο?大特性 創(chuàng)建對(duì)象的4種方式 構(gòu)造函數(shù)注意點(diǎn) 構(gòu)造函數(shù)的原型對(duì)象(使用方法/注意事項(xiàng)) 實(shí)例/實(shí)例化 實(shí)例/原型成員

面向?qū)ο蟮娜筇匦?/h4>
  • 封裝: 在JS中使用對(duì)象封裝一些變量和函數(shù)
    • 好處: 信息隱蔽, 方便擴(kuò)展維護(hù), 提高代碼的復(fù)用性
  • 繼承: 一個(gè)類(對(duì)象)獲取另一個(gè)類(對(duì)象)的屬性和方法的一種形式
    • 面向?qū)ο笳Z(yǔ)言定義: 是否有類的概念(c++ Java)
    • JS沒有類的概念, JS從這個(gè)角度說不是面向?qū)ο笳Z(yǔ)言. 但面向?qū)ο缶哂欣^承特性, 可以說JS支持面向?qū)ο笳Z(yǔ)言
  • 多態(tài): 同一操作, 作用于不同對(duì)象, 會(huì)產(chǎn)生不同行為(解釋)
    • 實(shí)現(xiàn): JS天生就具有多態(tài)的特性(弱類型語(yǔ)言)

創(chuàng)建對(duì)象的方式

  1. 字面量的方式

     var student = {
         name: 'zs',
         age: 16,
         class: '一分鐘精通JS'
     }
     //一個(gè)班級(jí)有N個(gè)學(xué)生, 通過字面量形式, 需要?jiǎng)?chuàng)建N個(gè)學(xué)生對(duì)象
     //問題: 創(chuàng)建多個(gè)同類型的對(duì)象時(shí), 大量代碼冗余(重復(fù)代碼)
     //價(jià)值: 只需要?jiǎng)?chuàng)建簡(jiǎn)單的幾個(gè)對(duì)象
    
  2. 內(nèi)置的構(gòu)造函數(shù)

    • 系統(tǒng)內(nèi)置的構(gòu)造函數(shù): Object | Array | Math | Date | Function | String | Number | Boolean

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

     function person(){
         var stu = new Object();
         stu.name= 'zs';
         stu.age= 16;
         stu.class=  '一分鐘精通JS';
         //返回該對(duì)象
         return stu;
     }
     var stu1 = person();
     var stu2 = person();    
     //問題: 兩個(gè)學(xué)生信息都一樣
    
     //優(yōu)化如下: 不同的信息當(dāng)做參數(shù)傳進(jìn)來(lái)                
     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
     //問題: 創(chuàng)建不同類型的對(duì)象時(shí), 無(wú)法分辨其類型       
    
  4. 自定義構(gòu)造函數(shù)-參照上一章構(gòu)造函數(shù)創(chuàng)建對(duì)象

    • 定義

      • 自己定義的構(gòu)造函數(shù)(首字母大寫)-通過this設(shè)置屬性/方法-使用new調(diào)用構(gòu)造函數(shù)創(chuàng)建對(duì)象
    • 執(zhí)行過程

      1. 通過new關(guān)鍵字調(diào)用構(gòu)造函數(shù),構(gòu)造函數(shù)內(nèi)部默認(rèn)創(chuàng)建一個(gè)新對(duì)象
      2. 將這個(gè)新對(duì)象賦值給this
      3. 通過this設(shè)置屬性和方法
      4. 默認(rèn)返回新創(chuàng)建對(duì)象
    • 返回值

      • 如果沒有顯示return, 默認(rèn)返回構(gòu)造函數(shù)內(nèi)部新創(chuàng)建的對(duì)象
      • 若寫了返回值, 要看具體情況
        • 如果返回值類型的數(shù)據(jù), 就直接忽略, 返回內(nèi)部新創(chuàng)建的對(duì)象
        • 若返回引用類型的數(shù)據(jù), 直接返回該數(shù)據(jù)(會(huì)覆蓋內(nèi)部新創(chuàng)建的對(duì)象)
    • 自定義構(gòu)造函數(shù)(區(qū)別于簡(jiǎn)單的工廠函數(shù))

      1. 函數(shù)名首字母大寫
      2. 自定義構(gòu)造函數(shù)內(nèi)部會(huì)默認(rèn)創(chuàng)建一個(gè)對(duì)象-默認(rèn)將這個(gè)對(duì)象賦值給this
      3. 默認(rèn)會(huì)返回新創(chuàng)建的對(duì)象
      4. 創(chuàng)建不同類型的對(duì)象時(shí), 可以分辨其類型

構(gòu)造函數(shù)注意事項(xiàng)

  1. 函數(shù)傳值: 函數(shù)當(dāng)做參數(shù)傳進(jìn)構(gòu)造函數(shù)
  2. 判斷對(duì)象的類型
    • 對(duì)象 instanceof 構(gòu)造函數(shù): 判斷指定對(duì)象是否由某個(gè)構(gòu)造函數(shù)創(chuàng)建出來(lái)
  3. 獲取對(duì)象類型: 構(gòu)造器屬性obj.constructor
  4. 構(gòu)造函數(shù)調(diào)用-區(qū)別于函數(shù)調(diào)用
    • new關(guān)鍵字: 默認(rèn)創(chuàng)建/返回對(duì)象

    • 構(gòu)造函數(shù): 對(duì)這個(gè)對(duì)象進(jìn)行一些初始化的操作(將創(chuàng)建對(duì)象賦值給this, 通過this綁定屬性/方法)

         function Person(name) {
              // this = obj;
      
              console.log(this);
              this.name = name;
              // return obj;
         }
        var p1 = new Person('zs');
      
        // 構(gòu)造函數(shù)也是一個(gè)函數(shù)
        var p2 = Person('ls'); // 可以這樣寫,但是不建議這樣做
        console.log(p2); // undefined, 直接調(diào)用構(gòu)造函數(shù),this指向window
      
       //分析打印結(jié)果
       <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>
      

構(gòu)造函數(shù)的原型對(duì)象

  1. 原型對(duì)象定義

    • 在構(gòu)造函數(shù)創(chuàng)建出來(lái)時(shí), 系統(tǒng)默認(rèn)會(huì)創(chuàng)建一個(gè)對(duì)象與這個(gè)構(gòu)造函數(shù)相關(guān)聯(lián), 這個(gè)對(duì)象稱為該構(gòu)造函數(shù)的原型對(duì)象


      構(gòu)造函數(shù)的原型對(duì)象
  2. 作用

    • 使用構(gòu)造函數(shù)創(chuàng)建出來(lái)的對(duì)象, 默認(rèn)就可以使用該構(gòu)造函數(shù)原型對(duì)象的屬性和方法
  3. 訪問原型對(duì)象: 構(gòu)造函數(shù).prototype

  4. 設(shè)置原型對(duì)象: 構(gòu)造函數(shù).prototype.name = 'name1';

    • 原型對(duì)象本質(zhì)也是一個(gè)對(duì)象, 可以利用對(duì)象的動(dòng)態(tài)特性設(shè)置原型對(duì)象
  5. 約定

    • 該對(duì)象構(gòu)造函數(shù)的原型對(duì)象
    • 構(gòu)造函數(shù)的原型對(duì)象(原型) | 對(duì)象的原型對(duì)象(原型)

實(shí)例與實(shí)例化

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

    p1.showName();  //張三
    p1.showAge();   //18
    p1.show();      //張三
    //p1.des();       //undefined ? 報(bào)錯(cuò)(Y)
    Person.des();     //undefined ? 報(bào)錯(cuò) ? 張三 ?Person(Y)

原型的使用方法

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

使用原型對(duì)象的注意事項(xiàng)

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

構(gòu)造器屬性相關(guān)

  • constructor屬性: 指向與之對(duì)應(yīng)的構(gòu)造函數(shù)
  • 對(duì)象.constructor: 訪問的是原型對(duì)象的constructor屬性

__proto__屬性

  • 定義
    • 構(gòu)造函數(shù)創(chuàng)建出來(lái)的對(duì)象, 默認(rèn)就有一個(gè)__proto__屬性, 該屬性指向該對(duì)象對(duì)應(yīng)的構(gòu)造函數(shù)的原型對(duì)象
  • 訪問原型對(duì)象-方式
    1. 構(gòu)造函數(shù).prototype
    2. 對(duì)象.__proto__
      • 注意點(diǎn): 在正式開發(fā)中, 不建議使用. 該屬性不是ES標(biāo)準(zhǔn), 是部分瀏覽器廠商方便調(diào)試程序


        __proto__和constructor結(jié)構(gòu)關(guān)系圖

hasOwnProperty()

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

isPrototypeOf()

  • 語(yǔ)法: 構(gòu)造函數(shù).protoType.isPrototypeOf(對(duì)象)
  • 定義: 判斷一個(gè)對(duì)象是否是指定對(duì)象的原型對(duì)象(判斷原型對(duì)象是否在整條原型鏈上)
  • instanceof區(qū)別: instanceof判斷一個(gè)對(duì)象是否是指定構(gòu)造函數(shù)的實(shí)例對(duì)象
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容