---
# System prepended metadata

title: 學習基礎JS

---

# 學習基礎JS
如果網頁只有HTML跟CSS就感覺有些空虛，是時候要邁入網頁設計的下個階段 --  JavaScript，而畢竟是全新的語言，而且跟HTML、CSS不同，JS學起來較有脈絡，所以我決定從基礎開始記錄，重點如下
## 變數
JS變數只有兩種宣告方式， const跟let (當然還有var，但好像漸漸被淘汰掉了)，兩者就差在以後是否能修改，至於是哪種型態就看你怎麼初始化，跟Python有點像，基礎變數型態有數字、字串、布林...有些比較龐大的內容會拆開來講，這邊就簡單介紹
```javascript=
let age = "17"; //數字，JS無整數、浮點數之分
const name = "Weber"; //單雙引號無差別
const fat = true;
age++; //age變18
name = "Weberorz"; //出錯，const不可修改
```
至於NULL跟undefined就輕鬆帶過
## 自定義函式
JS的自定義函式語法也是跟C++大不相同，C\++需要在定義時決定return跟傳進來的變數型態，反之JS不必決定return的變數型態，傳進來的變數型態也是浮動的
```javascript=
const age = 17;
const name = "Weber";
function WhatIsYourType(sth) {
    console.log(typeof(sth));
}
WhatIsYourType(age); //輸出number
WhatIsYourType(name); //輸出string
```
新的ES6還能用簡化版的arrow function
```javascript=
const age = 17;
const name = "Weber";
const WhatIsYourType = (sth) => {
    console.log(typeof(sth));
}
WhatIsYourType(age); //輸出number
WhatIsYourType(name); //輸出string
```
## 字串
字串有不少小東西可以講喔
### 字串格式化
JS的字串格式化是我目前看過最精簡直覺的，只要把原本的引號換成‵ ‵然後在需要放變數的地方寫$\{變數\}就行了
```javascript=
const age = 17;
const name = "Weber";
console.log(`Hi I'm ${name} and I'm ${age} years old`);
//輸出Hi I'm Weber and I'm 17 years old
```
### 字串合併
JS還能將不同的的資料型態合併成字串
```javascript=
const intro = "I'm Weber and I'm ";
const age = 17;
const anotherintro = " years old, yeah it's ";
const A_boolean = true;
const msg = intro + age + anotherintro + A_boolean;
console.log(msg);
//輸出I'm Weber and I'm 17 years old, yeah it's true
```
### 內建的method
JS內建很多方便的method，以下展示幾個應該還算常見的(至少是我目前看過的XD)
```javascript=
const msg = "I really want to eat pizza";
console.log(msg.toUpperCase()); 
//轉大寫，輸出I REALLY WANT TO EAT PIZZA

console.log(msg.toLowerCase()); 
//轉小寫，輸出i really want to eat pizza

console.log(msg.length);
//取得長度，輸出26

console.log(msg[14] + msg.charAt(15)); 
//兩種用index取得字元的方法，輸出to

console.log(msg.substring(21, 26));
//取得子字串，輸出pizza

const newMsg = msg.replace(/pizza/gi, "french fries"); 
//改變指定字，變成I really want to eat french fries
console.log(newMsg);
```
注意一下，這邊列出的method都不會改變字串原本的值
## 條件判斷
JS的if else只有邏輯運算子比較特殊一點，==跟!=只會比較值，資料型態不同不計較，===跟!==則會連同資料型態一起嚴格比較
```javascript=
if (17 == "17") {
    console.log(`17 == "17"`);
} //即使一個是數字、一個是字串，但對==沒差，回傳true，有輸出

if (17 != "17") {
    console.log(`17 != "17"`);
} //同上，對!=來說他們倆相同，回傳false，無輸出

if (17 === "17") {
    console.log(`17 === "17`);
} //因為資料型態不同，回傳false，無輸出

if(17 !== "17") {
    console.log(`17 !== "17"`);
} //同上，對!==來說型態不同就回傳true，有輸出
```
也就是說，在JS裡，17 == "17"但17 !== "17"
## 陣列
JS陣列跟C++差異頗大，不只初始化不同，method也多很多
### 初始化
我目前只看過這兩種初始化的方式
```javascript=
const foods = ["pizza", "fried rice", "pasta", "mash potato"]; 
//JS陣列能直接用中括號賦予值，還不用先宣告大小
const num = Array(5).fill(0); //跟C++的 int num[5]={} 一樣
```
### 各式method
超多~~~
```javascript=
console.log(foods[0]); 
//用index取得元素，輸出pizza

console.log(foods.length); 
//取得長度=4

console.log(foods.indexOf("fried rice")); 
//取得index=1

foods.pop(); 
//移除尾端元素

foods.push("milk shake"); 
//將milk shake推入尾端 

foods.shift();
//移除頂端元素

foods.unshift("apple pie"); 
//將apple pie 塞入頂端

foods.splice(3, 0, "strawberry"); 
//在位置3插入strawberry

foods.splice(2, 1, "ramen", "choco cookie");
//移除位置2以後的一個元素，並在2的位置插入ramen 跟 choco cookie

const AnotherFoods = foods.slice(); 
//複製陣列

//最後foods會變成['apple pie', 'fried rice', 'ramen', 'choco cookie', 'pasta', 'strawberry', 'milk shake']
```
話說splice好像能可以取代pop、push、shift、unshift，也太萬能XD
## 物件
這段偏向JS獨有，學起來就真的比較困難一點了
### 物件的基本組成
有點像class喔，可以把不同資料型態打包起來
```javascript=
const about_me = {
    name: "Weber",
    age: 17,
    too_fat: true,
    hobby: ["coding", "sleep", "play badminton"]
}
console.log(about_me.hobby); //輸出['coding', 'sleep', 'play badminton']
```
### Method跟this
這邊就有點讓人頭痛了，特別是this，我就盡可能的解釋吧~
this在英文中是代名詞，在JS中其實也是，但"代替誰"就是重點啦，this預設是代替window object
```javascript=
console.log(this);
//輸出Window {window: Window, self: Window, document: document, name: '', location: Location, …}跟一堆函式
```
但把this放在object裡時，就代表那個object，也就是說，this的含意會跟著所在位置而浮動，並常用在object中的function(又稱method)中
```javascript=
const about_me = {
    name: "Weber",
    age: 17,
    too_fat: true,
    hobby: ["coding", "sleeping", "playing badminton"],
    intro: function() { 
        console.log(`Hi I'm ${this.name} and I'm ${this.age} years old. I like ${this.hobby}`);
    }
}
about_me.intro();
//輸出Hi I'm Weber and I'm 17 years old. I like coding,sleeping,playing badminton
```
這邊有個大大大重點，就是如果method用arrow function寫會怎樣
```javascript=
const about_me = {
    name: "Weber",
    age: 17,
    too_fat: true,
    hobby: ["coding", "sleeping", "playing badminton"],
    intro: () => { 
        console.log(`Hi I'm ${this.name} and I'm ${this.age} years old. I like ${this.hobby}`);
    }
}
about_me.intro();
//輸出Hi I'm  and I'm undefined years old. I like undefined
```
欸，name怎麼變空字串，age跟hobby都變undefined，怎麼回事?!
這是因為ES6中，arrow function會被this給忽視，所以當this要去找object時會找不到，自然就變成undefined
那這樣設計用意何在?這就跟多層method有關了
```javascript=
const about_me = {
    name: "Weber",
    age: 17,
    too_fat: true,
    hobby: ["coding", "sleeping", "playing badminton"],
    intro: function() { 
        console.log(`Hi I'm ${this.name} and I'm ${this.age} years old. I like ${this.hobby}`);
        function am_i_fat() {
            console.log(`you're fat, that's ${this.too_fat}`);
        }
        am_i_fat();
    }
}
about_me.intro();
//輸出Hi I'm Weber and I'm 17 years old. I like coding,sleeping,playing badminton 跟 you're fat, that's undefined
```
在這個例子中，am_i_fat中的this.too_fat變成undefined，因為am_i_fat是用function定義，this去找object時被攔下來，離真正的about_me還太遠，就變成undefined了，這種情況有兩種解法
第一種是定義一個that = this，使其不再浮動
```javascript=
const about_me = {
    name: "Weber",
    age: 17,
    too_fat: true,
    hobby: ["coding", "sleeping", "playing badminton"],
    intro: function() { 
        console.log(`Hi I'm ${this.name} and I'm ${this.age} years old. I like ${this.hobby}`);
        const that = this;
        function am_i_fat() {
            console.log(`you're fat, that's ${that.too_fat}`);
        }
        am_i_fat();
    }
}
about_me.intro();
//輸出Hi I'm Weber and I'm 17 years old. I like coding,sleeping,playing badminton 跟 you're fat, that's true
```
但這樣寫有點弱弱的，所以arrow function被忽略的用處就誕生了
```javascript=
const about_me = {
    name: "Weber",
    age: 17,
    too_fat: true,
    hobby: ["coding", "sleeping", "playing badminton"],
    intro: function() { 
        console.log(`Hi I'm ${this.name} and I'm ${this.age} years old. I like ${this.hobby}`);
        const am_i_fat = () => {
            console.log(`you're fat, that's ${this.too_fat}`);
        }
        am_i_fat();
    }
}
about_me.intro();
//輸出Hi I'm Weber and I'm 17 years old. I like coding,sleeping,playing badminton 跟 you're fat, that's true
```
所以，何時該用一般function定義，何時該用arrow function就是一門重要課題
好欸，大致上就這樣，object的水很深啦，但基礎就先這樣吧ヘ(￣ω￣ヘ)
## 迴圈
Object終於講完了，來講點輕鬆的迴圈好了
目前學了兩種迴圈，第一種跟C++非常像，定義一個變數來在範圍內跑
```javascript=
for(let i = 0; i < 10; ++i) {
    console.log(i);
} //從1輸出到10
```
另一種則非常適合陣列，語法上有一點點類似C++的auto迭代器
```javascript=
const letters = [" ", "N", "e", "v", "r", "g", "o", "n", "a", "i", "y", "u", "p"];
const orders = [1, 2, 3, 2, 4, 0, 5, 6, 7, 7, 8, 0, 5, 9, 3, 2, 0, 10, 6, 11, 0, 11, 12];
let msg = "";
for(order of orders) {
    msg += letters[order];
}
console.log(msg);
//輸出Never gonna give you up
```
迴圈挺簡單的喔耶~
## Dom manipulation
終於到了最後一個觀念，而且終於要跟網頁互動了~這邊就直接拆成三個部分來講
### Selctor
Selector的功能就是選取網頁中的元素，有很多種寫法，我最常用的是querySelector系列
```javascript=
const topic = document.querySelector(".topic"); 
//用CSS語法即可選取，若有同類型只抓第一個

const content = document.querySelectorAll("p"); 
//抓多個元素用
```
當然還有getElementsByClassName跟getElementsById，只是就真的比較少用
### Style
基本上就是在JS裡寫CSS
```javascript=
const topic = document.querySelector("h1");
topic.style.color = "red";
```
標題就會從白色

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

變紅色

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

有夠醜，真正設計千萬別這樣搞XD

### addEventListener
壓軸的addEventListener就是偵測網頁活動的功能
#### click
```javascript=
const topic = document.querySelector("h1");
topic.addEventListener("click", () => {
    topic.style.color = "red";
    console.log("Your topic has bocome red");
})
```
效果如下

![](https://i.imgur.com/m1WbJfx.gif)

#### scroll
scroll的思路跟click比較不同，即使我們想要標題改變顏色，但被捲動的其實是document，不是h1，所以scroll要去抓"被捲動的容器"
```javascript=
const topic = document.querySelector("h1");
document.addEventListener("scroll", () => {
    topic.style.color = "red";
    console.log("Your topic has bocome red");
})
```

效果長這樣

![](https://i.imgur.com/RGFM5Ef.gif)

可以看到，在捲動的同時，console也瘋狂輸出

### querySelectorAll注意事項
這邊還有一個需要注意的小重點喔，querySelectorAll選出來的多個元素會被抓到一個NodeList裡，直接寫addEventListener跟style會出錯，需要開一個迴圈跑，一一下指令
```javascript=
const content = document.querySelectorAll("p");
for(contentChild of content) {
    contentChild.addEventListener("click", () => {
        console.log("red content");
    })
}
```
變這樣

![](https://i.imgur.com/6WfTooO.gif)

## 小小的結語
好累喔，一個不小心打到快兩點Σ(っ °Д °;)っ
東西有點多，學跟整理的時候都有點累，但感覺挺值得的，下個主題就是JS網頁實戰啦~

---

<ul style ="display: flex; flex-direction: row; width: 100%; justify-content: space-between;margin: 0; padding: 0;">
    <li style="list-style: none;"><a href = "https://hackmd.io/@WeberChang/BJ6op5i0t" >上一篇</a></li>
    <li style="list-style: none;"><a href = "https://hackmd.io/@WeberChang/rJBpwRsut">主頁</a></li>
    <li style="list-style: none;"><a href = "https://hackmd.io/@WeberChang/HJsIMGYFF">下一篇</a></li>
</ul>