---
# System prepended metadata

title: JS 核心 14 - 陣列、JSON、課後練習
tags: [' 陣列', ' JSON', 'JS 核心 ', 'JS ', ' JavaScript', ' Array']

---

---
title: 'JS 核心 14 - 陣列、JSON、課後練習'
tags: JS 核心 ,JS , JavaScript, 陣列, Array, JSON
description: 2021/02/10
---

JS 核心 -- 陣列、JSON、課後練習
===

## 陣列
> JavaScript 只有**原始型別**及**物件型別**兩種  
> 陣列也是物件型別的一種

### 使用陣列十字的方式定義陣列，直接插入**值**就可以了  
:pencil2: **取陣列的值 : array [索引位置]**  
:pencil2: **於陣列中插入新值 :　array.push (值)**
```
var newArray = [
  1,        // 原始型別: 數字
  '文字',    // 原始型別: 字串
  true,     // 原始型別: 布林值
  {
    name: '小明'  // 物件型別
  }
];
console.log(newArray);     // (4) [1, "文字", true, {…}]，有 4 筆資料 (如下圖)
console.log(newArray[3]);  // {name: "小明"}
newArray.push(5);          // 於陣列後方插入新值 5
console.log(newArray);     // (5) [1, "文字", true, {…}, 5]，有 5 筆資料
```
![](https://i.imgur.com/dDb409j.png)

:pencil2: **物件可以新增屬性 ;  <span class="red">陣列增加屬性內容，不會影響陣列長度**  </span>  
>  	新增屬性至陣列中，並不是增加一個資料進去陣列，故不會列入陣列長度。

若對陣列新增屬性 : 陣列長度不變，但新增屬性 name 則不屬於陣列裡的長度

```typescript=
var newArray = [
  1,       
  '文字',   
  true,    
  {
    name: '小明'  
  }
];
newArray.push(5);
newArray.name = '小明';
console.log(newArray);  // (5)[1, "文字", true, {…}, 5, name: "小明"]
```
  
:pencil2: **也可使用中括號 [ ] 新增值 : 若中間有空的部分，會自動補上空值 ( 顯示 undefined )，也會影響陣列的長度**  

跳過 "索引位置 6" ， 從 "索引位置 7" 插入新值  
"索引位置 6" 為空值，顯示 undefined

:pencil2: **使用 array.length 的方法把陣列長度印出**

```typescript=12
newArray[5] = '杰倫';     // 索引位置 5 為 '杰倫'
newArray[7] = '漂亮阿姨';  // 索引位置 7 為 '漂亮阿姨'
console.log(newArray);   // (如下圖)
// (8) [1, "文字", true, {…}, 5, "杰倫", empty, "漂亮阿姨", name: "小明"]
console.log(newArray[6]);     // undefined
console.log(newArray.length); // 8 (陣列長度)
```
![](https://i.imgur.com/gNp0meq.png)


:pencil2: **使用 for 迴圈 : 如何透過索引位置把資料一一陳列出來**  

先宣告 i = 0 ;  即索引位置等於 0  
當索引位置 < 陣列長度時，會依序地增加上去
```
for (var i = 0; i < newArray.length; i ++) {
    console.log(newArray[i])  // 即取得陣列所有內容
}
```

---

## JSON

### JSON 基本介紹
JSON 是個以純文字為基底去儲存和傳送簡單結構資料，可以透過特定的格式去儲存任何資料(字串,數字,陣列,物件)，也可以透過物件或陣列來傳送較複雜的資料。一旦建立了您的 JSON 資料，就可以非常簡單的跟其他程式溝通或交換資料，因為 JSON 就只是個純文字格式。

* JSON 結構和物件很像
* JSON 的屬性一定會加「雙引號 " "」使之成為字串 ( JSON 裡的屬性一定是字串型式 )
* JavaScript 物件是以「單引號 ' '」撰寫 ； JSON 一定是「雙引號 " "」 (否則會跳錯)

```
var family = {
  name: '小明家',
  members: {
    father: '老爸',
    mom: '老媽',
    ming: '小明'
  },
}
var json = JSON.stringify(family);  // 把 family 物件轉為字串
console.log(json);
// {"name":"小明家","members":{"father":"老爸","mom":"老媽","ming":"小明"}}
```

### :pencil2: 範例 : 試著用原生 AJAX 撈取遠方資料並轉為陣列  

**練習的 api : https://randomuser.me/api/**

```
var oReq = new XMLHttpRequest();
oReq.addEventListener('load', getData);
oReq.open('get', 'https://randomuser.me/api/');
oReq.send();

function getData(){
  console.log(oReq.responseText);          // 抓到的資料為字串
  console.log(typeof oReq.responseText);   // string
  var data = JSON.parse(oReq.responseText);// 把字串轉為 JavaScript 的物件，方便開發上的運用
  console.log(typeof data);  // object
}
```

### :pencil2: 範例 : 試著用 jQuery 撈取遠方資料 

Ｑ : 為什麼使用框架會直接得到 JavaScript 物件，而不是 JSON 字串 ？  
Ａ : 當使用框架，若傳入的是 JSON 格式，會自動轉為 JavaScript 物件，讓開發者少做轉檔步驟。  

> 使用 jQuery 框架撈取遠方資料將直接是 object

載入 jQuery CDN : <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>   
(要放在 all.js 前面)
 
```
$.ajax({
  url: "https://randomuser.me/api/",
}).done(function (data) {
  console.log(data);
  console.log(typeof data); // object
});
```
透過「NetWork」可看到「api/」這個檔案 → 點開右邊有「Response」為原本字串的型式

> JSON 並不是 JavaScript 的物件，是一個字串的型式，便於網路上做傳遞。

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

---

## 物件章節總結

### :pencil2: 範例練習

1. 請問以下物件格式是否正確 ?  
ans : 可以使用 console.log 檢查資料是否正常呈現
> 物件可以使用**數字或字串**作為屬性的內容  
> 所有屬性都是**字串**的格式 : 無論屬性是使用數字或字串，都屬於字串格式

```typescript=
var person = {
    name: '小明',
    age: 32,
    1: '2',
    gender: 'male',
    'interests': ['吃飯', '睡覺', '打動動'],
    greeting: function () {
        console.log('哈囉，你好');
    },
    '哈囉': function () {
        console.log('我是小明')
    }
 };
 console.log(person);  // (資料可正常呈現，物件格式正確)
```

2. 試著執行物件中的兩個函式
```typescript=15
person.greeting();     // 哈囉，你好
person['greeting']();  // 哈囉，你好
person['哈囉']();      // 我是小明
```

3. 運用以下陣列及 for 迴圈型式，執行 person 物件中的兩個函式

物件使用中括號 [ ] 取值 (中括號內可以插入變數)  
```typescript=18
var personMethod = ['greeting', '哈囉'];
for(var i = 0; i<personMethod.length; i++){
  // console.log(personMethod[i]);  // greeting  哈囉 (取出物件裡的屬性)
  person[personMethod[i]]();        // 哈囉，你好 / 我是小明 (同時執行兩個函式)
}
```

### :pencil2: 範例練習- 物件傳參考的特性

```typescript=
// 參考位置示意圖如下左圖
var family = {  // 新增物件，參考位置為 0x01
  deposit: 100000,
  name: '小明家',
  members: {    // 新增物件，參考位置為 0x02
      father: '老爸',
      mom: '老媽',
      ming: '小明'
  }
}
```
1. jQuery.assign 會使用淺層複製把值取出
    * <span class="red">**淺層拷貝也會宣告新的記憶體空間**</span>
    * 淺層拷貝會將第一層資料拷貝過來
2. 把值取出之前會先執行函式 changeName(family)，參數為 family 傳入函式內 (參考位置 0x01 帶入 data)，並修改 family 的值
3. family2 (使用淺層複製) 會接收原本 family 的值，產生新的記憶體空間為 0x03

> 物件是傳參考的概念，就算是傳遞函式的參數也是傳參考的概念

```typescript=11
// 參考位置示意圖如下右圖
function changeName(data) { // 宣告 data 的變數，把參考位置 0x01 傳入
  data.name = '杰倫家';    // 把傳入值的 name 改為 '杰倫家' (修改參考位置 0x01 的值)
  return data;            // 再把 data 傳回來 (以傳參考的型式傳遞)
}
var family2 = jQuery.extend({}, changeName(family));  // 使用淺層複製將值取出
family2.members.jay = '杰倫'; // 在 family2.members 屬性裡加入 '杰倫' 的值
console.log(family, family2); 
```
> 在第一層顯示相同資料（不同的參考路徑）， 修改其中內容….另一個不會更動
> 在第二層 members 是相同的參考路徑，修改其中屬性….另一個也會更動
> 
![](https://i.imgur.com/nKqfdM4.png)

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

```typescript=19
console.log('family.name', family.name);  // 杰倫家
console.log('family.members.jay', family.members.jay);  // 杰倫
console.log(family === family2);  // false  (family 和 family2 兩者以無關聯性)
console.log(family.members === family2.members);  
// true (兩者的屬性 members 共用同一個參考位置)
```
---

## 課後練習 
### :pencil2: 練習 1.

請問 a 會呈現什麼答案 ?
```
var a = {};
var b = a;
var c = b = { number : 1};
c.name = '小明';
console.log(a);       // {}
console.log(b);       // {number: 1, name: "小明"}
console.log(b == c);  // true
```
![](https://i.imgur.com/iKiZINP.png)


### :pencil2: 練習 2.
> forEach 把 family 陣列(物件)的屬性逐一取出後就直接 push 到新陣列中，屬於淺層複製。

```
var family = [{
    name : '小明家',
    members : {
        father : '父親',
        mom : '母親',
        ming : '小明',
    }
}];
var array = [];
family.forEach((item)=>{  // 淺層複製，相當於 for in 的語法
    array.push(item);
})
array[0].members.ming = 'casper';
console.log(family[0].members.ming);  // casper
console.log(array[0].members.ming);   // casper
console.log(family === array) // false (這兩者記憶體位子是不同的)
```
![](https://i.imgur.com/PDy1EVG.png)



### :pencil2: 練習 3.
```
var array = ['1','2','3','4','5'];
var array2 = array;
array2[4] = '6';
console.log('array: ' + array[4]);    // 6
console.log('array2: ' + array2[4]);  // 6
console.log(array,array2);   //  ['1','2','3','4','6']
console.log(array==array2);  // true
```
### :pencil2: 練習 4.

```
var a = {x: 1};
var b = a = {y: 2};
console.log('第一次:'+ a.y);   // 2
b.y = 3;
console.log('第一次:'+ a.y);   // 3
console.log('第一次:'+ b.y);   // 3
```
![](https://i.imgur.com/BuBrlTK.png)



## :memo: 學習回顧  
:::info
* 使用陣列十字的方式定義陣列，直接插入值就可以了
    * 取陣列的值 : array [索引位置]
    * 於陣列中插入新值 :　array.push (值)
    * 陣列增加屬性內容，不會影響陣列長度
    * 也可使用中括號 [ ] 新增值 : array[索引值]; 若中間有空的部分，會自動補上空值 ( 顯示 undefined )，也會影響陣列的長度
    * 使用 array.length 的方法把陣列長度印出
* JavaScript 物件是以「單引號 ’ '」撰寫 ； JSON 一定是「雙引號 " "」 (否則會跳錯)( JSON 裡的屬性一定是字串型式 )
* 物件可以使用數字或字串作為屬性的內容
    * 所有屬性都是字串的格式
    * 無論屬性是使用數字或字串，都屬於字串格式
* jQuery.extend({}, object); 會使用淺層複製把值取出 
    * 淺層拷貝也會宣告新的記憶體空間
    * 淺層拷貝會將第一層資料拷貝過來
* 物件是傳參考的概念，就算是傳遞函式的參數也是傳參考的概念
:::


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