「極速上手TypeScript」TypeScript進階“物件”

ice_moss發表於2021-10-29
[TOC]

一、定義

在TS中,我們定義一個物件不需要‘類’也不需要‘機構體’,如果我們需要寫一個物件就可直接寫,下面我們來看看:

//物件,直接建立物件即可
//定義物件em1
const em1 = {
 name: 'join', 
 gendr: 'male',
 salary: 8000,
 bonus: undefined  //bonus暫時不給值
 performance:5.5,
}console.log(em1)

就這樣,一個簡單的物件我們就定義好了,看看列印結果:

 "name": "join",
 "gendr": "male",
 "salary": 8000,
 "bonus": undefined,
 "performance": 5.5

下面我們再來看看裡面的一些細節:

  1. 指定型別:

    在上面例子中,我們的性別不一定是male,可以是female、other、unknown , 所以可以寫成:

    gendr: 'male' as ('male' | 'female' | 'other' | 'unknown'),

    當我們在賦值時也就只能賦值裡面指定的型別

  2. undefined:

    我們在上面例子中:

    bonus: undefined

    這裡使用undefined相當於沒寫這行,此時我們不能給bonus直接賦值,這裡仍然需要這樣寫:

    bonus: undefined as (number| undefined),//當然也可以寫其他型別

    下面我們來看一個小例子:

    const em1 = {
    name: 'join',
    gendr: 'male' as ('male' | 'female' | 'other' | 'unknown'),
    salary: 8000,
    bonus: undefined as (number| undefined),
    performance:5.5,
    }
    ​
    ​
    console.log(`${em1.name} has a salary of ${em1.salary}`)
    //判斷是否發獎金
    if (!em1.bonus){   //顯然bonus沒有給值,走if分支
     em1.bonus = em1.salary * em1.performance
     console.log(em1.bonus)
    }else{
     console.log('already for the bonus')
    }

    二、 巢狀

物件可以巢狀物件,也可以巢狀,物件也可以巢狀陣列

  1. 物件巢狀物件
    const em1 = {
     //物件巢狀物件
     name : {
     first:'三',
     last: '張',
     },
     gendr: 'male' as ('male' | 'female' | 'other' | 'unknown'),
     salary: 8000,
     bonus: undefined as (number| undefined),
     performance:5.5,
    }console.log(em1)  //列印
    列印結果:
    {
     "name": {
     "first": "三",
     "last": "張"
     },
     "gendr": "male",
     "salary": 8000,
     "bonus": 44000,
     "performance": 5.5,
    }
  2. 物件巢狀陣列
    const em1 = {
     //結構體套結構體
     name : {
     first:'三',
     last: '張',
     },
     gendr: 'male' as ('male' | 'female' | 'other' | 'unknown'),
     salary: 8000,
     bonus: undefined as (number| undefined),
     performance:5.5,
     badges: ['優先員工','遲到王'],   //string[……]
    }

    三、JSON(stringify/parse)的應用

我們可以使用json將物件轉換為json格式(是一種網路傳輸字元格式),也可以將字串轉換為物件

  1. 將物件轉換為字串

    const em1 = {
     //結構體套結構體
     name : {
     first:'三',
     last: '張',
     },
     gendr: 'male' as ('male' | 'female' | 'other' | 'unknown'),
     salary: 8000,
     bonus: undefined as (number| undefined),
     performance:5.5,
     badges: ['優先教師','遲到王'],   //string[……]
    }
    ​
    
    console.log('將物件轉為字串')
    const s: string = JSON.stringify(em2)   //JSON.stringify()  物件轉為字串
    console.log(s)

    看看列印結果:

    "{"name":{"first":"","last":""},"gendr":"male","salary":8000,"bonus":44000,"performance":5.5,"badges":["優先教師","遲到王"]}"
  2. 將字串轉換為物件

    (連線上段程式碼)

    console.log('將字串轉為物件')
    const em3 = JSON.parse(s)
    console.log(em3)

    列印結果:

    {
     "name": {
     "first": "三",
     "last": "張"
     },
     "gendr": "male",
     "salary": 8000,
     "bonus": 44000,
     "performance": 5.5,
     "badges": [
     "優先教師",
     "遲到王"
     ]
    } 

    四、函式

    其實函式我們在基礎語法的時候就已經遇見了,但我們只做了簡單介紹,下面我們來具體講解一下TS的函式:

    1. 函式的定義

      定義一個加法的函式
      
      function add(a: number, b: number){
       console.log(a + b) //列印結果
      }
      //一個簡單的加法函式就定義好了
      //呼叫:
      add(100, 100) //輸出結果:200

      在函式中’a’和‘b’都是形參(形式引數),而我們在呼叫時的具體資料為實參(實際引數)

      我們繼續深入,上面的函式是沒有返回值的,再來定義一個有返回值的函式:

      function add(a: number, b: number):number{  //引數列表後面這需要加冒號及返回值型別
       return a + b
      }
      //呼叫:
      const num = add(100, 100)
      console.log(num)  //輸出:200
  3. 可選引數/預設引數/可變引數列表

    可選引數:當我們在定義和使用函式時,有時需要多個引數,有時候引數有需要的少一些,例如:我們要一個既可以計算2個數有可以計算3個數的函式,這是候就需要可選引數,下面來定義一個有可選引數的函式:

    function add(a: number, b: number, c?: number):number{ //使用’?‘表示可選引數
    if(c){
     return a + b + c
    } else{
     return a + b
     }
    }
    //呼叫:
    console.log(add(100, 100, 100))  //輸出:300
    console.log(add(100, 100))       //輸出:200

    其實在add函式結構中還有更簡單的語法:

    //method1
    function add(a: number, b: number, c?: number):number{
    return c ? a + b + c : a + b
    }//method2
    function add(a: number, b: number, c?: number):number{
    return a + b + (c||0) 
    }

    預設引數:我們在函式定義時就將某些引數設值

可變引數列表:

function add(a:number, 
    b: number, 
    c?:number,
    d: number=0, //預設引數
     ...e:number[]):number{ //不能直接return a + b + c   c 可能是undefined
     let sum = a + b + (c||0) + d
     for(let i = 0; i < e.length; i++){
         sum = sum + e[i]
     }
     return sum
}
  1. 使用物件型別作為引數

    在定義函式的時候,如果我們需要的引數較多,例如下面:

    function sendRequest(
     url: string,
     method: 'GET' | 'POST' | 'PUT',
     header: object,
     data: string,
     requireAuth:boolean,
     retry: boolean,
     retrytimeout: number,
    ){
    return data
    }//這種函式當我們需要的引數過多時,函式在呼叫的時候就低效
    sendRequest(https://test.com,
     'GET',
     {contentType:'application/json'}, 
     '{"name":"join"}', 
     ture,
     ture,
     3000)
    //看吧,如果該函式在其他地方,我們就不知道這些實參究竟是什麼了,比如:’true‘,’3000‘等

    下面就來看看使用物件型別作為引數:

    function sendRequest(params:{   //以物件型別作為引數
         url: string,
         method: 'GET' | 'POST' | 'PUT',
         header: object,
         data: string,
         requireAuth:boolean,
         retry: boolean,
         retrytimeout?: number,
        }){
         console.log(params)
        }//呼叫:
    sendRequest({
         url: 'http:www.test.com',
         method: 'GET',
         header: {
         contentionType: 'application/json',
         },
         data: '',
         requireAuth: true, 
         retry: true,
         retrytimeout: 3000,
        })
    //這樣就非常直觀明瞭

    輸出結果:

    {
     "url": "http:www.test.com",
     "method": "GET",
     "header": {
     "contentionType": "application/json"
     },
     "data": "",
     "requireAuth": true,
     "retry": true,
     "retrytimeout": 3000
    } 

    五、方法

我們在’四‘中介紹了函式,下面我們就可以來介紹方法,為物件定義方法了,直接來看在TS中是如何為物件定義方法:定義方法和函式的區別是函式前面需要使用關鍵字function,方法則不需要,其他都一樣

const em1 = {
     name: 'join',
     gendr: 'male' as ('male' | 'female' | 'other' | 'unknown'),
     salary: 8000,
     bonus: undefined as (number| undefined),
     performance:5.5,

     upDataBonus(){    //em1的方法——發獎金
         if (!em1.bonus){
             em1.bonus = em1.salary * em1.performance
             console.log(em1.bonus)
         }else{
             console.log('already for the bonus')
         } 
     },

     getSalary(){   //返回工資
         return em1.salary
     }
}//這裡需要注意:當我們列印物件em1時,我們在沒有調em1的方法時,它是沒有列印結果的
console.log(em1)

輸出結果:

{
 "name": "join",
 "gendr": "male",
 "salary": 8000,
 "bonus": undefined,
 "performance": 5.5
}

所以我們需要呼叫:

em1.upDataBonus()
console.log(em1.getSalary())
console.log(em1)//輸出結果:
44000 
8000 
{
 "name": "join",
 "gendr": "male",
 "salary": 8000,
 "bonus": 44000,
 "performance": 5.5
}

其實這裡還有問題,我們在em1的內部定義方法為什麼這裡還是:em1.bonus,em1.salary,em1.performance

 upDataBonus(){    //em1的方法——發獎金
     if (!em1.bonus){
             em1.bonus = em1.salary * em1.performance
             console.log(em1.bonus)
     }else{
             console.log('already for the bonus')
      } 
    },

     getSalary(){   //返回工資
         return em1.salary
 }

原因是:我們的變數會去全域性找,在全域性中我們肯定找不到(沒有在全域性中定義)

如果我們改變物件的名字豈不是要修改方法裡的很多變數,更何況有點物件我們沒有命名

這裡的解決:使用this關鍵字

const em1 = {
     name: 'join',
     gendr: 'male' as ('male' | 'female' | 'other' | 'unknown'),
     salary: 8000,
     bonus: undefined as (number| undefined),
     performance:5.5,upDataBonus(){    //em1的方法——發獎金
         if (!this.bonus){
             this.bonus = this.salary * this.performance
             console.log(this.bonus)
         }else{
             console.log('already for the bonus')
         } 
   },

    getSalary(){
       return this.salary
    }
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章