---
# System prepended metadata

title: JS 核心 5 - 型別
tags: [' 運算子、型別與文法', JS 核心, ' Javascript']

---

---
title: 'JS 核心 5 - 型別'
tags: JS 核心, Javascript, 運算子、型別與文法
description: 2021/02/03
---

JS 核心 -- 型別
===

## 動態型別
#### JavaScript 屬於動態語言，在執行階段才確立型別。
* 宣告變數時不需指定型別。
* 執行過程可以任意更換變數的型別。
```typescript=
// 創造階段
var myName;      // myName會被提升 (在記憶體裡準備一個空間)
// 執行
myName = '小明';  // 在執行階段，把 '小明' 賦予到變數上 (這才具備有字串這個型別)
```
#### <span class="red">檢視型別 (值的本身已具備型別)</span>  
把值賦予在變數上，變數的型別來自於值
```typescript=5
console.log(typeof myName);  // string
console.log(typeof '小明');   // string
```

### 顯性轉換
當變數的值直接被賦予另一個型別的值。  
原本 num 是數字，後來被賦予變成字串。
```
var num = 1;
console.log(typeof num);  // number
num = '文字';
console.log(typeof num);  // string
```

### 隱性轉換
可對照參閱[運算子內容](https://hackmd.io/@peggyted0129/B1cNt0veu)。要了解轉換的過程中，型別是如何變化的。  
將<span class="red">數值加上任一字串</span>，型別就會立即轉為<span class="red">字串</span>。  
將<span class="red">字串乘上任一數字</span>，型別就會立即轉為<span class="red">數字</span>。

```
var num = 1;
console.log(num , typeof num);  // 1 "number"
num = num + '';
console.log(num , typeof num);  // 1 string
num = num * 3;
console.log(num , typeof num);  // 3 "number"
```

## 原始型別 及 物件型別
#### JavaScript 的型別分為兩大類：
* 原始型別 ( Primitive Type）: 
    * 不允許自由擴增屬性
    * number、string、boolean 有屬性 & 方法可以使用，因為有原始型別包裹物件(父元素的關係)
    * number、string、boolean 因為有原始型別包裹器，在包裹成物件後，即可透過該物件自由擴增屬性，而使用 new 所建構的型別，在 typeof 都會是 object
* 物件型別 ( Object Type ) : 
    * 物件型別有兩種，分別是 Array、 Object，可以自由擴增屬性  

(只要記得那些是原始型別就好了，因為剩下的就是物件型別。)


![](https://i.imgur.com/Srd5cpm.png)

**範例** : 
null 的型別是 object，是 JavaScript 長久以來的錯誤 (也無法修正)
```
var a = null;
console.log(typeof a);  // object
```
**範例** : e 這個未定義的變數的型別是 undefined, 這是typeof 對 undefined 變數的保護措施。
```
console.log(e);         // e is not defined
console.log(typeof e);  // undefined (若有變數未宣告，使用 typeof 去查詢會顯示 undefined)
```
### 物件型別
前面提到，基本型別會有「屬性」以及「方法」是因為這些型別有著相對應的包裹物件。
### 包裹物件 : 使這些原始型別有一些方法可以使用。

```
var a;
a = 'ming ' ;           // 後面有加一個空格
console.log(a);         // a (只是字串)
console.log(a.length);  // 5 ， a 有多長 (4個字元+1個空白字元)
console.log(a.toUpperCase());  // MING+空格 (以大寫呈現)
console.log(a.trim());  // 把 a 後面的空白修剪掉
```
**範例 (建構式)**  
```typescript=
var a = 'ming'          // a 是一個原始型別為字串的變數
console.log(typeof a);  // string

var e = new String(a);  // e 是一個透過建構式建立的物件
console.log(a,e);
console.log(typeof e);  // object
```
它會透過對應的物件建構器將 "a" 包裝成一個 String 「物件」，然後回傳對應的屬性後，即刻銷毀恢復成基本型別。  
e 是一個物件，_proto_ 是包裹物件的原型，裡面包含了這個物件可以使用的方法。
![](https://i.imgur.com/I2rEkhu.png)

試著分別為物件與基本型別的 string 設定「屬性」
```typescript=7
e.color = 'red';
a.color = 'red';

console.log( e.color );      // 'red'  (包裹物件可以自由擴增屬性)
console.log( a.color );      // undefined (原始型別不允許自由擴增屬性)
```

<span class="green">需要原始型別變數時，盡量不要使用建構式來宣告，因為這樣便會宣告出一個物件型別，而非原始型別，操作上還是會跟原始型別不太一樣。</span> (直接 var a = 'ming' 就好了)



## :memo: 學習回顧 
:::info
* <span class="red">JavaScript 屬於動態語言，在執行階段才確立型別 (值的本身已具備型別)。</span>
* 顯性轉換 : 當變數的值直接被賦予另一個型別的值。
* 隱性轉換 : 將數值加上任一字串，型別就會立即轉為字串。
將字串乘上任一數字，型別就會立即轉為數字。
* 原始型別 ( Primitive Type）: 不允許自由擴增屬性
* number、string、boolean 因為有原始型別包裹器，可透過該物件自由擴增屬性。
    * 包裹物件 : 使這些原始型別有一些方法可以使用。
* 當我們嘗試著要去存取 String、Number 與 Boolean 這三種基本型別的屬性時，它就只會在「那一刻」被轉型為該類別的「物件」。
:::

## :+1: 相關參考文件 
:::info
[深入理解 JavaScript 物件屬性](https://ithelp.ithome.com.tw/articles/10193747)  
[基本型別包裹器](https://ithelp.ithome.com.tw/articles/10193902)  
[JavaScript 就是一堆物件的概念](https://wcc723.github.io/javascript/2017/12/09/javascript-object/)
:::

<style>
.red {
  color: red;
}
.green {
  color: green;
}
</style>