web-4
講師
Eating
目錄
- JS 介紹
- JS 變數
- JS 運算子
- JS 流程控制
- JS 型別
- 非同步
- Github Page
JS 基礎
JS 是啥
JavaScript 簡稱 JS ,是一個程式語言,專門用於網頁前端*1的互動。
他能夠實現(不只)以下功能
變更網頁上的元素、做簡單運算、製作遊戲、動態抓取資料、建立假的多頁網站
它的優點就是超簡單,瀏覽器通常只認他,但就是因為太簡單了所以寫 JS 可能被看不起

*1 透過 node.js,JavaScript 也能用來撰寫後端。
JavaScript 跟 JAVA 有啥關係
那時候很 JAVA 很紅所以她取名子的時候就蹭一下 JAVA 的熱度
啊不要問我 JAVA 是啥我不會,感覺不是很好用啦。

Hello, World!
學程式第一件事就是 Hello, World!
感覺 JS 的 Hello, World! 應該最好寫了。
1. 打開 F12
2. 找到 Console
3. 輸入 :
就好了!
你也可以試試看這個:

console.log("Hello, World!");alert("hello, world");那正常一點的引入方式是啥
建立一個 script.js 的檔案
<script type="text/javascript" src="script.js"></script>然後在 HTML 中可以這樣引入,打開這個網頁後他的輸出會在 F12 的 Console 中
那正常一點的引入方式是啥
不想開檔案也可以這樣
<script>
// 在這裡寫 JS 程式碼
console.log(123);
</script>然後在 HTML 中直接放一個 script 標籤,JS 直接寫裡面
JS 基礎 實作
引入一個檔案後,用剛剛兩個方法輸出 Hello, World!
JS 語法-變數
變數
變數是一個存東西的東西
相信大家都知道是啥了
變數宣告
宣告就是讓電腦知道這個變數存在
Python 都不宣告超怪
var a = 1;
let b = 2;
const c = 3;變數宣告
作用域
相信大家也都會了因為 APCS 會考
啊但那是 C++
啊不過他們很像
ㄜ有幾個不一樣的地方
變數宣告
作用域
先講一些常識
1. 全域變數通常在所有東西外面嘛然後大家都可以用他
2. 在 Function 中宣告的變數只有在 Function 中能用
3. 還有一個區塊變數就是在{}裡面,每個{}中宣告的變數就只有他能用
4. 讀取的時候名字一樣會讀到域最小(最近)的那個
變數宣告
作用域
let g = 100; // 全域變數
function test() {
let x = 10; // 區域變數
if (true) {
let y = 20; // 區塊變數
}
}
test();
變數宣告
作用域 C++ vs JS
let g = 100; // 全域變數
function test() {
let x = 10; // 區域變數
if (true) {
let y = 20; // 區塊變數
var z = 5; // 他會變區域變數
}
//這裡讀的到 z!
}
test();
不同的地方 1. 有 var 這種鬼東西
他會自己提升成區塊變數
變數宣告
作用域 C++ vs JS
// JavaScript
console.log(x); // undefined (不會報錯!)
var x = 5;不同的地方 2. var 可以先用他再宣告,初始值是 undefined
變數宣告
作用域 C++ vs JS
let age = 25;
let name = "小明";
let price = 99.99;
let isStudent = true;
age = "二十五"; // 可以改成字串
age = [1, 2, 3]; // 也可以變成陣列
age = { value: 30 }; // 甚至可以變成物件不同的地方 3. 不用指定類型
ㄜ這功能評價有好有壞但我是覺得爛透了
變數宣告
所以 let 和 const 是啥
let age = 18;
age = 19; // 可以改變
age = 20; // 可以再改變
const pi = 3.14;
pi = 3.14159; // 錯誤!const 不能重新賦值let 就是最正常的變數宣告
const 是宣告一個你不會改他的變數 好其實 c++ 也有所以你們應該懂
變數命名
嗯
先講一些常識
1. 必須使用字母、_、$ 作為開頭
2. 名稱可包含數字(0-9)
3. 'A' ~ 'Z' 和 'a' ~ 'z' 皆可使用且大小寫敏感(例:Name ≠ name)
4. 不能使用保留字(啊保留自有啥自己去找)
變數命名
好習慣
一般變數用:小寫開頭、大寫分隔
常數變數通常用:全大寫、"_"分隔
函式可用動詞開頭:calculateTax、getUserInfo
變數如果是布林值就用疑問句開頭:isActive 、shouldUpdate
let score = 55; // 分數
let extraPoints = 5; // 加分
let finalScore = score + extraPoints;
const PI = 3.14159;
const EULER_NUMBER = 2.71828;變數參考
有點怪
分兩種變數,一個是基本型別
另一個是參考型別
他們在"複製"的時候有不同行為
變數參考
基本型別 會複製"值"
string, number, boolean, null, undefined, symbol
// 基本型別 - 複製的是「值」
let a = 10;
let b = a; // b 得到 10 的「副本」
b = 20; // 改變 b
console.log(a); // 10 - a 不受影響 ✓
console.log(b); // 20變數參考
參考型別 會複製"地址"
object, array, function
// 物件 - 複製的是「地址」(參考)
let person1 = { name: "小明", age: 18 };
let person2 = person1; // person2 指向「同一個物件」!
person2.age = 20; // 改變 person2
console.log(person1.age); // 20 - person1 也變了!
console.log(person2.age); // 20const student1 = { name: "小明", score: 85 };
const student2 = student1; // 共用同一個物件!
student2.score = 95;
console.log(student1.score); // 95 - 被改了!
console.log(student2.score); // 95
const arr1 = [1, 2, 3];
const arr2 = arr1; // 這不是複製!是共用!
arr2.push(4);
console.log(arr1); // [1, 2, 3, 4] - arr1 也被改了!
console.log(arr2); // [1, 2, 3, 4]
至於要怎麼複製請看後面有一個 展開運算子
JS 語法-變數-實作
APCS 不會考
超簡單
let z = 0;
function f(x) {
if (true) {
console.log(x);
var x = 10;
}
z += x;
console.log(x);
}
f(f(x));
var x = 2;
console.log(x);
console.log(z);依序輸出啥/或是哪裡會噴錯
猜猜看變數可以存多大
真好玩
JS 語法-資料型態
資料型態
隨便啦只講有用一點的
模板字串
let product = "心";
let price = 100000000;
console.log(`您購買的商品是${product},價格為 ${price} 元`);
// 您購買的商品是心,價格為 100000000 元資料型態
隨便啦只講有用一點的
Undefined&Null:
Undefined:變數宣告但未賦值
Null:表示「無值」,通常是開發者明確設定的
條件判斷的時候他們都是 false
let notAssigned; // 變數宣告但未賦值
console.log(notAssigned); // undefined
let empty = null; // 明確將變數設為 null
console.log(empty); // null資料型態
隨便啦只講有用一點的
物件
反正就 key 對 value
key 通常是字串
value 隨便你
const phoneBook = {
小明: "0928440308",
小美: "0919680246",
張三: "0982727329",
李四: 0968802962
};資料型態
隨便啦只講有用一點的
物件
let person = {
name: 'Alice',
age: 25,
greet: function () {
console.log('Hello!');
}
};
person.age = 3000;
console.log(person.name,person.age); // Alice,3000
person.greet(); // Hello!資料型態
隨便啦只講有用一點的
物件
const student = {
name: "小明",
age: 18,
grade: "A"
};
const keys = Object.keys(student);
console.log(keys); // ["name", "age", "grade"]
// 搭配 forEach 遍歷
keys.forEach(key => {
console.log(`${key}: ${student[key]}`);
});資料型態
隨便啦只講有用一點的
陣列
// 宣告陣列
let num1 = ['壹', '貳', '參'];
// new Array(),功能與上面的相同
let num2 = new Array('壹', '貳', '參');
console.log(num1); // [ '壹', '貳', '參' ]
console.log(num2); // [ '壹', '貳', '參' ]
// 也可以宣告空陣列
let emptyArray = [];
console.log(emptyArray); // []let num = [1, 2, 3];
// 訪問元素
console.log(num[2]); // 3
// 修改元素
num[2] = 2; // [ 1, 2, 2 ]
// 新增元素
num.push("3"); // [ 1, 2, 2, '3' ]
num.unshift(false); // [ false, 1, 2, 2, '3' ]
num[5] = 5; // [ false, 1, 2, 2, '3', 5 ]
// 刪除元素
num.pop(); // [ false, 1, 2, 2, '3' ]
num.shift(); // [ 1, 2, 2, '3' ]
// 查看長度
console.log(num.length); // 4
// 陣列轉字串
console.log(allNum.join('-')); // 1-2-2-3let num = [1, 5, 3, 7, 5];
// 搜尋元素
console.log(num.indexOf(5)); // 1
console.log(num.includes(3)); // true
console.log(num.includes(2)); // false
// 複製&切割
let subArray = num.slice(1, 3); // [ 5, 3 ]
// 新增&刪除
num.splice(3, 2, 3); // 從索引 3 刪除 2 個元素,並插入 3
console.log(num); // [ 1, 5, 3, 3 ]
// 排序
num.sort(); // [ 1, 3, 3, 5 ]
num.reverse(); // [ 5, 3, 3, 1 ]
// 合併
let moreNum = [10, 23, 12];
let allNum = num.concat(moreNum); // [ 5, 3, 3, 1, 10, 23, 12 ]資料結構
陣列操作(ES6)
const numbers = [1, 2, 3, 4, 5];
// 不用 map 的寫法(笨方法)
const doubled = [];
for (let i = 0; i < numbers.length; i++) {
doubled.push(numbers[i] * 2);
}
// 用 map 的寫法(聰明方法)
const doubled = numbers.map(function(num){
return num * 2
});
console.log(doubled); // [2, 4, 6, 8, 10]map 填的參數是一個 Function ,會自動把陣列的每個值傳入那個 Function 並且將原本的值替換成函式的返回值
const students = [
{ name: "小明", score: 85 },
{ name: "小華", score: 92 },
{ name: "小美", score: 78 }
];
// 加上 index 參數
const processed = students.map((student, index) => ({
id: index + 1, // 從 1 開始編號
name: student.name,
score: student.score,
grade: student.score >= 90 ?'A' :
student.score >= 80 ? 'B' :'C',
passed: student.score >= 60
}));
console.log(processed);
// [
// { id: 1, name: "小明", score: 85, grade: "B", passed: true },
// { id: 2, name: "小華", score: 92, grade: "A", passed: true },
// { id: 3, name: "小美", score: 78, grade: "C", passed: true }
// ]至於這邊的 Function 跑去哪? => 又是啥可以看下一章
const students = [
{ name: "小明", score: 85 },
{ name: "小華", score: 92 },
{ name: "小美", score: 78 }
];
// 加上 index 參數
const processed = students.map((student, index) => ({
id: index + 1,
...student, // 保留原有的 name 和 score
grade: student.score >= 90 ? 'A' :
student.score >= 80 ? 'B' : 'C',
passed: student.score >= 60
}));
console.log(processed);
// [
// { id: 1, name: "小明", score: 85, grade: "B", passed: true },
// { id: 2, name: "小華", score: 92, grade: "A", passed: true },
// { id: 3, name: "小美", score: 78, grade: "C", passed: true }
// ]const users = [
{ id: 1, name: "小明", age: 18 },
{ id: 2, name: "小華", age: 20 },
{ id: 3, name: "小美", age: 19 }
];
// 根據 ID 找使用者
const user = users.find(u => u.id === 2);
console.log(user);
// { id: 2, name: "小華", age: 20 }
// 根據名字找
const user2 = users.find(u => u.name === "小美");
console.log(user2.age); // 19資料型態
隨便啦只講有用一點的
陣列
還有很多 ES6 的好用東西要看一下
超推薦下面這篇文章我之前要用都是查他
JS 語法-資料型態
-實作
JS 語法-運算子
運算子
超簡單
有次方可以直接用還不錯
let a = 10;
let b = 3;
console.log(a + b); // 13
console.log(a - b); // 7
console.log(a * b); // 30
console.log(a / b); // 3.33333333333333
console.log(a % b); // 1
console.log(a ** b); // 1000運算子
超簡單
這也是常識
let x = 10;
x += 5; // 等價於 x = x + 5,結果為 15
x -= 3; // 等價於 x = x - 3,結果為 12
x *= 2; // 等價於 x = x * 2,結果為 24
x /= 4; // 等價於 x = x / 4,結果為 6
x %= 5; // 等價於 x = x % 5,結果為 1運算子
超簡單
這也是常識
let y = 5;
console.log(y == "5"); // true
console.log(y === "5"); // false
console.log(y != 3); // true
console.log(y !== "5"); // true
console.log(y > 3); // true
console.log(y <= 5); // true運算子
超簡單
這也是常識
// && (AND):兩邊都為 true,結果才為 true
console.log(true && false); // false
console.log(true && true); // true
// || (OR):只要一邊為 true,結果就是 true
console.log(true || false); // true
console.log(false || false); // false
// ! (NOT):反轉布林值
console.log(!true); // false
console.log(!false); // trueconsole.log(!!false); // false,假
console.log(!!undefined); // false,未定義
console.log(!!null); // false,空值
console.log(!!""); // false,空字串
console.log(!!NaN); // false,不是數字
console.log(!!0); // false,(正)零
console.log(!!-0); // false,負零
console.log(!!true); // true,真
console.log(!!'hi'); // true,字串 hi
console.log(!!1); // true,一
console.log(!![]); // true,空陣列
console.log(!![0]); // true,有一個零的陣列
console.log(!![1]); // true,有一個一的陣列運算子
展開運算子
const arr1 = [1, 2, 3];
const arr2 = [...arr1]; // 展開後複製
console.log(arr2); // [1, 2, 3]
arr2.push(4);
console.log(arr1); // [1, 2, 3] - 原陣列不受影響
console.log(arr2); // [1, 2, 3, 4]運算子
展開運算子
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
// 舊方法
const merged1 = arr1.concat(arr2);
// 新方法 - 用展開運算子
const merged2 = [...arr1, ...arr2];
console.log(merged2); // [1, 2, 3, 4, 5, 6]
// 可以加入額外元素
const merged3 = [0, ...arr1, 3.5, ...arr2, 7];
console.log(merged3); // [0, 1, 2, 3, 3.5, 4, 5, 6, 7]運算子
展開運算子
const basic = { name: "小明", age: 18 };
const extra = { city: "台北", hobby: "coding" };
const merged = { ...basic, ...extra };
console.log(merged);
// { name: "小明", age: 18, city: "台北", hobby: "coding" }運算子
展開運算子
const user = { name: "小明", age: 18 };
// 展開在前 - 會被覆蓋
const result1 = { ...user, age: 20 };
console.log(result1); // { name: "小明", age: 20 } ✓
// 展開在後 - 覆蓋前面的值
const result2 = { age: 20, ...user };
console.log(result2);
// { age: 18, name: "小明" } - age 被 user.age 覆蓋了!JS 語法-流程控制
流程控制
if (條件) {
// 當條件為 true 時執行的程式碼
}
if (條件) {
// 當條件為 true 時執行的程式碼
}
else {
// 當條件為 false 時執行的程式碼
}if else
流程控制
for
for (初始化; 條件; 更新) {
// 迴圈內執行的程式碼
}
// 範例
for (let i = 0; i < 5; i++) {
console.log(i); // 輸出 0, 1, 2, 3, 4
}跟 C++ 一樣
流程控制
WHile
while (條件) {
// 程式碼
}
// 無限迴圈
while (true) {
// blablabla
}跟 C++ 一樣
喔然後不要在無線迴圈操作 DOM 會爛掉
(操作 console 也會)
流程控制
break、continue
for (let i = 0; i < 10; i++) {
if (i === 5) {
break; // 當 i 等於 5 時,停止迴圈
}
console.log(i); // 0 1 2 3 4
}
for (let i = 0; i < 10; i++) {
if (i % 2 === 0) {
continue; // 略過偶數
}
console.log(i); // 1 3 5 7 9
}流程控制
switch
switch (表達式) {
case 值1:
// 當表達式等於 值1 時執行的程式碼
break;
case 值2:
// 當表達式等於 值2 時執行的程式碼
break;
...
default:
// 當表達式不符合任何情況時執行的程式碼
}條件語句
超好用
let age = 18;
let canVote = age >= 18 ? "Yes" : "No";
console.log(canVote); // Yes
(canVote == "Yes") && console.log("歡迎投票!");
// canVote 是 Yes 才會印出來函式
一樣基礎
// 基本函式
function greet(name) {
return "你好, " + name;
}
console.log(greet("小明")); // "你好, 小明"
// 有預設值
function greet(name = "訪客") {
return "你好, " + name;
}
console.log(greet()); // "你好, 訪客"
console.log(greet("小華")); // "你好, 小華"
// 多個參數
function add(a, b) {
return a + b;
}
console.log(add(5, 3)); // 8
// 沒有 return (回傳 undefined)
function sayHi(name) {
console.log("嗨, " + name);
}
sayHi("小明"); // 只印出訊息,沒有回傳值
const greet = function(name) {
return "你好, " + name;
};
console.log(greet("小明")); // "你好, 小明"// 基本箭頭函式
const greet = (name) => {
return "你好, " + name;
};
console.log(greet("小明")); // "你好, 小明"
// 傳統函式
const numbers = [1, 2, 3];
const doubled = numbers.map(function(num) {
return num * 2;
});
// 箭頭函式 - 簡潔多了!
const doubled = numbers.map(num => { return num * 2});
// 箭頭函式 - 更簡潔的!
const doubled = numbers.map(num => num * 2);反正就是省略 Function
直接寫括弧傳入參數之後用 =>{} 在 {} 中正常寫函式
如果只有一行而且剛好是 return 的話可以連 {} 和 return 都省略
JS 語法-類型!??
大家都說 JS 類型是智障
啊他到底哪裡智障
| 靜態型別 | 動態型別 | |
|---|---|---|
| 定義 | 在編譯時期就指定變數的型別 | 在執行時期才會決定變數的型別 |
| 特點 | 型別不可隨意更改 | 型別可隨時更改 |
| 優缺 | 提升程式的執行效能與穩定性 | 程式更加靈活,但寫的時候較容易出錯 |
| 例子 | C、C++、Java | JavaScript、Python、Ruby |
大家都說 JS 類型是智障
啊他到底哪裡智障
| 強型別 | 弱型別 | |
|---|---|---|
| 定義 | 不允許隱式轉換或任意混合使用不同型別的資料 | 允許隱式轉換,可混合不同型別的資料 |
| 特點 | 除非你主動說要轉換類型不然不會變 | 型別可能會偷偷被更改 |
| 優缺 | 要把字串和庶子接起來要轉換 | 可能會意外轉換,加上 js 判斷相等的方式很酷 |
| 例子 | Python、Java | JavaScript、PHP |
大家都說 JS 類型是智障
這是有點智障又有點聰明的地方
1 + "2" // "12"
"3" + 4 + 5 // "345"
3 + 4 + "5" // "75"
[] + 1 // "1"
// 通常 + 的參數不是數字的時候結果會是字串
"10" - 2 // 8
"6" * "7" // 42
"20" / 2 // 10
// 通常其他的時候他會盡量轉成數字
"" - 1 // -1
[] - 3 // "-3"
false - 2 // -2
// 這些通常是 0大家都說 JS 類型是智障
這是超怪超智障的地方
0 == "0" // true
0 == [] // true
"0" == [] // false
!!0 // false
!!"0" // true
!![] // true
NaN == NaN // false
null > 0 // false
null == 0 // false
null === 0 // false
null >= 0 // ture
Number(null) // 0let num = 123;
let bool = true;
let str1 = String(num); // "123"
let str2 = num.toString(); // "123"
let str3 = String(bool)); // "true"
let str = "123";
let num1 = Number(str); // 123
let num2 = parseInt("123px"); // 123(忽略非數字部分)
let num3 = parseFloat("3.14"); // 3.14(保留小數部分)
console.log(Number(true)); // 1
console.log(Number(false)); // 0
console.log(Boolean(1)); // true
console.log(Boolean(0)); // false
console.log(Boolean("Hello")); // true
console.log(Boolean("")); // false
console.log(Boolean(null)); // false這是顯式轉換 蠻正常的 啊轉成同的類型之後去比較就不會出事
大家都說 JS 類型是智障
用 == 去比較的時候它會自動幫我們轉換
反正他愛怎麼轉就怎麼轉,所以會出現上面那些情況。
如果要避免的話可以改用 === 去比較
let y = 5;
console.log(y == "5"); // true
console.log(y === "5"); // falseJS 非同步處理
非同步處理
setTimeout、setInterval
把很多東西放在同步的單線程會卡住,在網頁這種互動的地方更重要。
舉例來說你正在讀取最新的資料的時候,使用者可能要同時填寫表單並驗證?如果用單線程的同步操作可能會整個卡死。
非同步處理
console.log("開始");
setTimeout(() => {
console.log("3秒後執行");
}, 3000); // 3000 毫秒 = 3 秒
console.log("結束");
// 輸出順序:
// 開始
// 結束
// 3秒後執行 (3秒後才出現)setTimeout
非同步處理
let count = 0;
setInterval(() => {
count++;
console.log(`執行第 ${count} 次`);
}, 1000); // 每 1 秒執行一次
console.log("結束")
// 輸出:
// 結束
// 執行第 1 次
// (1秒後) 執行第 2 次
// (1秒後) 執行第 3 次
// ... 持續執行setInterval
// 錯誤:計時器會一直執行
function startTimer() {
setInterval(() => {
console.log("執行中...");
}, 1000);
}
startTimer();
startTimer(); // 現在有兩個計時器在跑!
// ✓正確:儲存 ID 以便清除
let timerId;
function startTimer() {
if (timerId) {
clearInterval(timerId); // 先清除舊的
}
timerId = setInterval(() => {
console.log("執行中...");
}, 1000);
}Githib pages
要複習一下
Github pages
你應該有下面這個畫面

Github pages
點設定

Github pages
點 Pages

Github pages
點 None

Github pages
點 master 或是它顯示 main 就一樣點他

Github pages
點 Save

然後等他一下
Github pages
重新整理之後就會出現下面那樣
點進去
他會預設顯示你的根目錄下面的 index.html 檔案(或是 .md 檔案)
如果你不叫 index.html 就要在連結上加入
/<檔案名稱>.html 才能顯示



web-4
By 翊庭jx06 T
web-4
- 27