es6 對象學習 總結

 ====================es6對象 新增的對象字面量語法==========================
    
    1. 成員速寫:
     如果對象字面量初始化時,成員的名稱來自於一個變量, 並且和變量的名稱相同,則可以進行簡寫
     es6以前使用返回對象,需要以下的寫法:
        /**
         * @description: 創建要給用戶, 返回一個對象
         * @param :  loginId 登錄的id
         * @param :  loginPwd 登錄的密碼
         * @param :  nickName 暱稱
         * @return:  {*} 返回一個對象
         */
        function createUser(loginId, loginPwd, nickName) {
            return {
                loginId: loginId,
                loginPwd: loginPwd,
                nickName: nickName,
                id: Math.random()
            }
        }

        es6後,可以這麼寫:
        /**
         * @description: 創建要給用戶, 返回一個對象
         * @param :  loginId 登錄的id
         * @param :  loginPwd 登錄的密碼
         * @param :  nickName 暱稱
         * @return:  {*} 返回一個對象
         */
        function createUser(loginId, loginPwd, nickName) {
            return {
                loginId,
                loginPwd,
                nickName,
                id: Math.random()
            }
        }

    2. 方法名速寫:
      在對象字面量初始化時, 方法可以省略冒號和function:
      es6以前:
      const user = {
           name:'twinkle',
           age: 100,
           sayHello: function(){
               
           }
       }

       es6以後:
        const user = {
           name:'twinkle',
           age: 100,
           sayHello(){
               
           }
       }

    3. 計算屬性名
      有的時候,初始化對象時, 某些屬性名可能來自於某個表達式,在計算中可以使用中括號來表示該屬性名是通過計算得到的。

      例如:
        const prop1 = "name";
        const porp2 = "age";
        // es6 以前創建一個帶有變量的對象屬性需要以下做法
        const user = {};
        user[prop1] = "twinkle";
        user[porp2] = 100;

        // es6後可以這麼寫,初始化就可以賦值:
        const user1 = {
          [prop1]: "twinkle",
          [porp2]: 100  
        }

    ====================es6對象 新增的對象API==========================
    以下方法都是靜態方法,直接應用在Object上:
    1. Object.is(obj1, obj2) 用來判斷兩個對象是否相等
    用於解決一些歷史遺留問題: 如: NaN === NaN // false \
                                 +0 === -0 // false
     用於判斷兩個數據是否相等,基本上是嚴格相等(===)是一致的,除了以下兩點:
      1.  NaNNaN
      2. +0-0                            


    2. Object.assign() 用於對象的混合
    如: const obj1 ={a: 123, b: 234}
        const obj2 = {c, 123, a:234}
        這個方法與es7 的...是一樣的 如{...obj1, ...obj2}  與 Object.assign(obj1, obj2) 相同 
        Object.assign(obj1, obj2) 這個方法會改動第一個參數,返回的是obj1,巧妙的寫法 Object.assign({}, obj1, obj2)          

    3. Object.getOwnPropertyNames 的枚舉順序
      Object.getOwnPropertyNames() 這個方法之前就存在, 只是沒有明確的要求,如何排序由瀏覽器廠商來排序。
      es6規定了該方法的數組的排序如下:
        先排數字(升序),在排其他 
       
     
    4. Object.setPrototypeOf() 用於設置某個對象的隱士原型
    比如: Object.setPrototypeOf(obj1, obj2) 相當於 obj1.__proto = obj2

   
    ===================es6面向對象================
    面向對象: 是一種編程思想, 和具體的語言無關
    對比面向過程: 
     面向過程: 思考的切入點是功能的步驟
     面向對象: 思考的切入點是對象的劃分

    如: [大象裝冰箱]

    面向過程的思考如下:
    1. 冰箱門打開
    
    2. 大象裝進去

    3. 冰箱關上

    面向對象的思考如下:
    
    大象對象

    冰箱對象
    冰箱的方法: 打開
                關閉
                裝東西
    步驟: 1. new 一個冰箱 調用打開的方法
           2. new 一個大象 冰箱裝好大象
           3. 冰箱的關閉
    
    總結: 面向對象用於大型的項目,更好的維護;面向過程用於小型的項目,快速開發       
           
   類: 構造函數的語法糖 class

   傳統的構造函數的問題
     function Animal(type, name, age, sex) {
            this.type = type;
            this.name = name;
            this.age = age;
            this.sex = sex;
        }

        Animal.prototype.print = function () {
            console.log("種類", this.type);
            console.log("名字", this.name);
            console.log("年齡", this.age);
            console.log("性別", this.sex);
        }

        // 面向對象中, 上面的屬性和方法的定義,統稱爲一個類

        const a = new Animal("狗", "旺財", 3, "男")
        a.print();

   1. 屬性和原型方法定義分離, 降低了可讀性
   2. 原型成員可以被枚舉, 方法可以被變量
   3. 默認情況下,構造函數仍然可以當作普通函數使用

   類的特點:
        class Animal {
            constructor(type, name, age, sex) {
                this.type = type;
                this.name = name;
                this.age = age;
                this.sex = sex;
            }
            /**
             * @description: 打印方法
             * @param : 
             * @return: 
             */
            print() {
                console.log("種類", this.type);
                console.log("名字", this.name);
                console.log("年齡", this.age);
                console.log("性別", this.sex);
            }
        }
        const a = new Animal("狗", "旺財", 3, "男")
        a.print();

   1. 類聲明不會被提升, 與letconst 一樣,存在暫時性死區
   2. 類中的所有代碼均在嚴格模式下執行
   3. 類的所有方法都是不可枚舉
   4. 類的所有方法內部都無法當作構造函數使用
   5. 類的構造器必須使用 new 來調用


   類的其他書寫方式:

   1. 可計算的成員名:
   如: cosnt printName = "print";
      const obj = {
        print(){
           console.log('打印')}
      }

      調用方式:
      obj.[printName]()   就是等於obj.print()

   2. getter 和 setter 方法  
   es5 中可以使用 Object.defineProperty() 可以定義某個對象成員屬性的讀取和設置
   es5以前使用函數來給一個對象來賦值或者取值
   使用getter和setter控制的屬性不在原型上
   使用方法: 直接在函數前面加上get set 構造器裏面還是原來的寫法

   3.靜態成員: 構造函數本身的成員, 通過new 出來的成員叫做實例原型;
   例如: 上面的Animal.abc = "abc" 這個叫做靜態成員
          而new 出來的東西叫做實例成員
    使用static 定義的成員,就是靜態成員
    
   4. 字段初始化器(es7): 寫成員的時候可以直接賦值
   如: class Test{
       static a = 1;
       b = 2;
       c = 3
   } 
   相當於: class Test{
       constructor(){
           this.a = 1;
           this.b = 2;
           this.c = 3;
       }
   }

   注意: 1. 使用static的字段初始化器,添加的是靜態成員
          2. 沒有使用static的字段初始化器, 添加的成員位於對象上
          3. 箭頭函數使用初始化器,存在對象上面,不在原型上
          可以通過console.dir(類名)

   5. 表達式:
   如:
   const A = class{ //匿名類,表達式

   }

   6. 裝飾器(es7): 提示方法以及過時,因爲有的方法更新過程,會在其他地方使用,所以提示後面開發者
   使用裝飾器標記方法過期了
   語法: @+ 名稱
   如: class Test {
       @Obsolete
       print(){

       }
   }
// 現在用不了,需要使用babel或者用typescript
   function Obsolete(target, methodName, descriptor){
      // target  function Test
      // print
      // {value: function print(){},……}
       const oldFunc = descriptor.value;
       descriptor.value = function(...args){
           console.warn(`${methodName}` 方法已經過時了)
           oldFunc.apply(this, args)
       }
   }


   es6類的繼承: 如果兩個類AB,如果可以描述爲:BA, 則AB形成繼承關係
   如果BA,則:
    1. B繼承自A
    2. A派生B
    3. BA的子類
    4. AB的父類

    如果AB的父類,則B會自動擁有A的所有實例成員
    es6以前通過, call() 來實現繼承
    如:
    
        // 以下代碼實現了了一個動物的方法,要實現狗繼承於動物
        function Animal(type, name, age, sex){
            this.type = type;
            this.name = name;
            this.age = age;
            this.sex = sex;
        }

        Animal.prototype.print = function(){
            console.log(this);
        }

        function Dog(name, age, sex){
            // 這麼寫可以實現屬性的繼承,但是Dog裏面沒有動物類上的打印方法;
            // 原因: 動物的原型上纔有打印的方法, 但是狗的只是使用了動物的構造函數。
            // 但是動物的原型並沒有繼承過來, 所以要使狗的隱式原型要使用動物的原型
            Animal.call(this, "犬類", name, age, sex);
        }
        // 這樣就形成了繼承關係了
        Object.setPrototypeOf(Dog.prototype, Animal.prototype);
        
   es6的做法如下:
   extends: 繼承
   super: 1. 直接當作函數來調用,表示父類構造函數
          2. 如果當作對象使用,表示調用父類的方法super.print()  

   例如:
      class Animal {
            constructor(type, name, age, sex) {
                this.type = type;
                this.name = name;
                this.age = age;
                this.sex = sex;
            }

            print() {
                console.log(this)
            }
        }

        class Dog extends Animal{
            constructor(name, sex, age){
                super("犬類", name, age, sex);
            }
        }

    注意: 
     es6要求,如果定義了constructor,並且該類式子類,則必須在constructor的第一行手動調用父類的構造函數
     如果子類不寫constructor,則會有默認的構造器,該構造器需要的參數和父類一模一樣,並且調用父類的構造器


     用js製作抽象類:
      該類不能被實例話,只能被繼承
     this 執行具體的類
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章