---
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 筆資料
```

: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 (陣列長度)
```

: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 撈取遠方資料
Q : 為什麼使用框架會直接得到 JavaScript 物件,而不是 JSON 字串 ?
A : 當使用框架,若傳入的是 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 的物件,是一個字串的型式,便於網路上做傳遞。

---
## 物件章節總結
### :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 是相同的參考路徑,修改其中屬性….另一個也會更動
>


```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
```

### :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 (這兩者記憶體位子是不同的)
```

### :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
```

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