JS 有兩大類型別:原始型別 與 物件型別


#兩大類型別圖:

#原始型別(primitives):

#物件型別:

#如何判斷是不是物件(型別)?

  • 物件型別特質:可以自由擴增屬性。
//物件
const obj = {};
obj.age = 32;
console.log(obj); 

---- console區 ------
{age: 32}
//陣列 PS:實戰/平常中千萬不要這樣寫!!!!
const arr = [];
arr.age = '他今年滿18';
arr.push(18);
console.log(arr); 

---- console區 ------
[18, age: '他今年滿18']
//函式 把函式作為物件使用(實戰中可能見到)
const fn = function () {

}; 
fn.mySlogan = '我一個詭異的函式物件';
console.log(fn); 

---- console區 ------
//通常console.log無法看見函式內部內容
ƒ () {

}
---- console.dir()區 ------
這個方法可以看見物件型別中的內容
ƒ fn()
mySlogan: "我一個詭異的函式物件"
arguments: null
caller: null
length: 0
name: "fn"
//原始型別只有純值,無法拓增屬性
const num = 1;
    num.mySlogan = '今天是好天氣';
console.dir(num); 

---- console.dir區 ------
1

dir使用時機?25.00

型別方法在哪裡?

  • 原始型別的方法來自於-boxing-原始型別包裹物件:

    console.dir(String)
    //所有字串 數字型別方法都存在這
    ---- console.dir區 ------
    ƒ String()
    可以點選開發人員工具中顯示出的prototype:String屬性
    
  • 運作原理new operator://實戰千萬不要這樣寫

    • 以下由new來創建(物件):
      let str = new String(' 我是特別的 ');//這會是一個物件
      console.log(str)
      console.log(str.trim())
      ---- console區 ------
      String {' 我是特別的 '}
      我是特別的
      
let str2 = new String(' 我是特別的 ');
console.log(typeof str)
console.log(str == str2)
---- console區 ------
Object
false
//但這明明是兩個一樣的東西字串>純值>>變質了
-----------------------------

記住:str中存的原來是字串>原始型別>純值,無法拓增屬性,但是.....

str.myName = '加入了怪東東'
console.log(str)
---- console區 ------
String {' 我是特別的 ', myName: '加入了怪東東'}

#型別轉換(JS型別可以自由轉換)

#顯性轉換

  • 1-1:boxing-原型型別包裹物件 Number,String

    let price = 100; //number
      console.log(String(price)) //string
      console.log(BigInt(price))  //bigint
      console.log(Symbol(price))  //symbol(100)
    
  • 1-2:原型方法(要注意原型鍊中有沒有該方法/有沒有原始型別包裹物件)

      console.log(price.toString()) //string
       !!要注意原型鍊中有沒有該方法/有沒有原始型別包裹物件
       console.log(undefined.toString()) //TypeError
    
  • 1-3:數值型別相關方法

    console.log(Number('100元')) //NaN
    console.log(Number.parseInt('100元')) //100
    console.log(parseInt('100元')) //100
    因為在window全域物件下也有一個parseInt()的方法
    console.log(window.parseInt === Number.parseInt) //true
    
  • 3:正負運算子,正負一元運算子(一定會轉型成number)

    //二元運算子的例子:轉型成string
    console.log(1 + '1') //二元運算子轉型為string  '11'
    >>> `+`是運算子
    >>> 1是一個運算元
    >>> '1'是一個運算元
    這是二運算元
    
    //ㄧ元運算子的例子:轉型成number
    console.log(+ '1') //會轉型成number 1
    >>> `+`是運算子
    >>> '1'是一個運算元
    這是一運算元
    
    //ㄧ元運算子的例子:轉型成number
    console.log(+true) //會轉型成number 1
    
    //ㄧ元運算子的例子:轉型成number
    console.log(+'50元') //NaN
    NaN的型別是number
    
  • 2-2:邏輯 NOT 運算子(會轉型成boolean)

console.log(!true) //false
console.log(!false) //true

console.log(Boolean(0)) //先轉型成false
console.log(!0) //true 因為0是falsy value

console.log(Boolean('1')) //true
console.log(!'1') //false
console.log(!!'1') //true

隱性轉換(盡量不要去作隱性轉換)

    • 運算子(二元運算子)
      • 規則1:前後運算元,如果其中一個為字串型別,+就會被視為“字串運算子”
      • 規則2:前後運算元,如果無法轉成原始型別(那就是物件型別),+也會被視為“字串運算子”
      • 規則3:上述情況以外,+會被視為“算數運算子”
        console.log(100+100) //200 算數運算子
        console.log('我是'+'無敵') //'我是無敵' 字串運算子
        

練習:

console.log(1+'1') //"11" string +字串運算子
console.log(1+true) //2  number +算術運算子
console.log(1+ {}) //1[Object object] string +字串運算子
console.log(String({})) //[Object object]>>算數中,所有物件都是用String({})去做轉型所以會是 [Object Object]
console.log(1 + []) //"1" string +字串運算子
console.log(1 + [1,2,3]) //"11,2,3" string +字串運算子
console.log(1+ {a:1}) //1[Object Object]
特例:bigInt無法和其他型別/數字直接作轉換
console.log(1 + 1n) //error
特例:symbol()
console.log(1 + symbol(1)) //cannot a symbol value to a number
console.log( '1' + symbol(1)) //cannot a symbol value to a string
console.log({} + symbol(1)) //cannot a symbol value to a string
特例:bigInt無法和其他數值直接作轉換
console.log(1 + 1n) //error
  • 算術運算子(- / * )
    console.log(1 - '1') //0 number
    console.log(100 * true) //100 number
    console.log(100 - true) //99 number
    
    ### 例外狀況 BigInt
    console.log(1n * 100);

其他類型比較

console.log([100] * 100); //10000 number
console.log([100,1] * 100);// NaN
//陣列轉型
console.log([100].toString());
console.log([10, 0].toString()); // 10 ,0
console.log(Number([10, 0].toString())); // NaN

型別比較

1.寬鬆相等:值相等,型別 不需要
console.log(1 == '1'); //true

  • Number Strung Boolean 這三個進行比對時,都會以Number進行轉型

    console.log("1" == true) // true
    console.log(1 == "1") // true
    console.log("0" == false) // true
    
  • null,undefined 不轉型(都是false),但null與undefined兩者相比都是true

    cosole.log(null == 0) //false
    cosole.log(null == '') //false
    cosole.log(null == false) //false
    console.log(null == undefined) //true
    console.log(null == null) //true
    console.log(undefined == undefined) //true
    
  • 物件與非物件比對:物件與其他類型比對時,會透過“boxing包裹物件”將物件轉為相同型別
    //使用原始型別包裹物件作轉型
    console.log([0] == 0) //true
    console.log('[object object]' == {}) //true 因為String({}) [object object]
    console.log(['a'] == 'a') //true
    
  • 1:布林採用Number轉型
    console.log([] == false); //true Number([]) >> 0 >>falsy value
    console.log([1] == true) //true
    console.log([2] == true) //false
    
  • 2:陣列轉數值,會先toString()再套用Number
  • 3: 例外冷門:
    let sym1 = Symbol(1)
    let sym2 = Symbol(1)
    console.log(sym1 == sym2) // false
    
  • 例外:Bigint,轉為數學值,沒有NaN,沒有小數點,沒有最大值其他概念與Number接近
    console.log(Number.MAX_SAFE_INTEGER) //9007199254740991
    console.log(9007199254740991 == '9007199254740991') //true
    console.log(9007199254740993 == '9007199254740992') //true >>>已經超過最大安全數值,因此比對結果有問題
    console.log(9007199254740993n == '9007199254740992') //false 超過安全數值之後,有加入BigInt相對在比對上是穩定的
    console.log(9007199254740993n == '9007199254740993') //true 超過安全數值之後,有加入BigInt相對在比對上是穩定的
    console.log(100n * 100n) //10000n
    

2.嚴格相等:值 與 型別 完全相同 (開發使用這個)
console.log(1 === '1'); //false

3.嚴格相等有例外狀況

//false版
console.log(NaN === NaN); //false
console.log(undefined === null); //false
console.log({} === {}); //false
console.log([] === []); //false
console.log(new Number(0) === new Number(0)); //false
原理是記憶體位址指向不同
//true版
console.log(+0 === -0); //true
console.log(Infinite === Infinite); //true

真假值(待補充)

筆記來源:

  • <js直播工程師養成班-六角學院>
  • <javascript 核心篇-六角學院>
#六角學院 javascript 六角學院-js直播養成班 js核心篇







你可能感興趣的文章

執行緒與同步、非同步概念

執行緒與同步、非同步概念

JS30 Day 18 筆記

JS30 Day 18 筆記

Kotlin 練功場 - Android 組

Kotlin 練功場 - Android 組






留言討論