# 學習基礎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";
```
標題就會從白色

變紅色

有夠醜,真正設計千萬別這樣搞XD
### addEventListener
壓軸的addEventListener就是偵測網頁活動的功能
#### click
```javascript=
const topic = document.querySelector("h1");
topic.addEventListener("click", () => {
topic.style.color = "red";
console.log("Your topic has bocome red");
})
```
效果如下

#### 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");
})
```
效果長這樣

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

## 小小的結語
好累喔,一個不小心打到快兩點Σ(っ °Д °;)っ
東西有點多,學跟整理的時候都有點累,但感覺挺值得的,下個主題就是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>