JavaScript(縮寫 JS)是一種開發人員用來建立互動式網頁的程式設計語言,可以提升使用者體驗,這篇文章是我學習 JavaScript 的筆記內容。

1. JavaScript 入門

1.1 JavaScript 簡介

JavaScript(縮寫 JS)是一門基於原型和頭等函式的多範式進階直譯程式語言,它支援物件導向程式設計、指令式編程和函數式程式設計。

【範例:印出 Hello World!】

打開.html文件,在<body>標籤內,新增<script>標籤,並在內輸入console.log("Hello World!");

<script>console.log("Hello World!");</script>

開啟瀏覽器,進入開發人員工具,即可在 Console 頁面中看到輸出結果:Hello World!

【註解】

單行註解:

// 註解

多行註解:

/*
    註解
    註解
*/

1.2 資料、資料型態

數字:

3;
3.14;
-3;

字串:

("hello!");

布林值:

true;
false;

空值:

null;

未定義:

undefined;

1.3 變數、常數

1.3.1 變數

輸出 undefined:

let x;
console.log(x);

輸出 10:

x = 10;
console.log(x);

輸出 true:

x = true;
console.log(x);

輸出 null:

x = null;
console.log(x);

輸出 hello:

let abc = "hello";
console.log(abc);

1.3.2 常數

輸出 100,且 x 不可變:

const x = 100;
console.log(x);

1.4 運算符號

1.4.1 算數運算

使用加減乘除做運算。

輸出 1:

let x = 7 % 3;
console.log(x);
  • %:取餘數。

1.4.2 指定運算

指定一個值給變數。

輸出-2

x = 1;
x += 1;
x -= 4;
console.log(x);
  • =:將符號右邊的值賦予到左邊的變數中。
  • +=:a = a + b。
  • -=:a = a - b。

1.4.3 比較運算

透過布林邏輯得到 TRUE 或 FALSE。

輸出 true:

x = 4 == 4;
console.log(x);
  • 等於:==
  • 不等於:!=
  • 完全等於:===
  • 完全不等於:!==

1.4.4 單元運算

針對單一資料做運算。

輸出 4:

x = 3;
x++;
console.log(x);
  • 變數加一:++
  • 變數減一:–
  • 布林值反運算:!

1.4.5 邏輯運算

針對布林值的運算,使用 And(&&)、Or(||)。

輸出 false:

let test = true && false;
console.log(test);

輸出 true:

let test1 = true || false;
console.log(test1);

1.4.6 乘法運用

彈出視窗讓使用者輸入數字,並將兩個數字相乘,印出結果:

let n1 = prompt("請輸入一個數字", "");
let n2 = prompt("請輸入二個數字", "");
let result = n1 * n2;
console.log(result);

1.5 流程控制:判斷式

if 判斷式:

let money = prompt("要領多少錢?", "請輸入數字");
if (money < 100) {
  console.log("太少!");
} else if (money <= 100000) {
  console.log("OK!");
} else {
  console.log("NO!");
}
console.log("判斷式結束");

1.6 流程控制:迴圈

while 迴圈:

let n = 0;
while (n < 3) {
  console.log(n);
  n++;
}
let n = 1;
let result = 0;
while (n <= 10) {
  result = result + n;
  n++;
}
console.log(result);

for 迴圈:

for (let n = 0; n < 3; n++) {
  console.log(n);
}
result = 0;
for (let n = 1; n <= 10; n++) {
  result += n;
}
console.log(result);

1.7 流程控制:迴圈指令

break,強制結束整個迴圈:

let n = 0;
while (n < 5) {
  if (n == 4) {
    break;
  }
  console.log(n);
  n++;
}

continue,跳過本次迴圈,但不會結束迴圈,會繼續下一圈:

for (let n = 0; n < 5; n++) {
  if (n == 3) {
    continue;
  }
  console.log(n);
}

1.8 JavaScript 函式基礎

印出 hello:

function test() {
  console.log("hello");
}
test();

印出 world:

function show(message) {
  console.log(message);
}
show("world");

1.9 函式回傳值

return 會終止函式執行,並指明函式呼叫器(function caller)要回傳的數值。

【範例 1】

function test() {
  console.log("hello");
  return "bbb";
}
let value = test();
console.log(value);

輸出結果:

hello
bbb

【範例 2】

function divide(n1, n2) {
  let result = n1 / n2;
  console.log(result);
  return result;
}
let ans = divide(4, 2);
console.log(ans);

輸出結果:

2
2

1.10 物件基礎

【範例】

let man = new Object();
man.age = 18;
man.name = "小王";
man.talk = function () {
  console.log("hello", this.name, this.age);
};
console.log(man);
console.log(man.age);
console.log(man.age > 20);
man.talk();

【範例:JSON】

let man = {
  age: 15,
  name: "小王",
  talk: function () {
    console.log("hello", this.name, this.age);
  },
};
console.log(man);
man.talk();

1.11 陣列物件

【範例 1:利用 push,將數字推進去陣列】

let grades = [];
grades.push(70);
grades.push(50);
grades.push(90);
console.log(grades);

【範例 2:取得陣列中特定位置的數字】

let grades = [70, 50, 90];
grades.push(25);
grades.push(100);
console.log(grades);
console.log(grades[0]);
console.log(grades[1]);
console.log(grades[2]);
console.log(grades[3]);
console.log(grades[4]);
console.log(grades.length);
console.log(grades[grades.length - 1]);

輸出結果:

(5)[(70, 50, 90, 25, 100)]
70
50
90
25
100
5
100

【範例 3:用 for 取得陣列資料】

let grades = [70, 50, 90];
grades.push(25);
grades.push(100);
for (let i = 0; i < grades.length; i++) {
  console.log(grades[i]);
}

輸出結果:

70
50
90
25
100

【範例 4:平均數,算總和】

let grades = [70, 50, 90];
grades.push(25);
grades.push(100);
let total = 0;
for (let i = 0; i < grades.length; i++) {
  total = total + grades[i];
}
let avg = total / grades.length;
console.log(total);
console.log(avg);

輸出結果:

335
67

2. JavaScript 動態網頁開發

2.1 HTML DOM 觀念

HTML DOM:

console.log(window);

開啟瀏覽器,進入開發人員工具,即可在 Console 頁面中看到 window 物件。

視窗寬度高度:

console.log(window.innerWidth, window.innerHeight);

透過 screen 取得螢幕尺寸:

console.log(window.screen.width, window.screen.height);

取得網址列內容:

console.log(window.location.href);

更改網址列內容:

window.location.href = "https://www.google.com/";

document:

console.log(window.document);
console.dir(document);

取得網頁標題:

console.log(document.title);

更改網頁標題:

document.title = "新標題";

取得 body 標籤:

console.log(document.body);

更改網頁主畫面內容(body 內容):

console.log(document.body.innerHTML);
document.body.innerHTML = "hello!!!!!!";

2.2 HTML DOM 網頁畫面操作

【範例:按鈕與文字變化】

<h3>Hello!</h3>
<div id="content">練習網頁畫面操作</div>
<button onclick="change();">點我</button>
function change() {
  // 取得標籤物件
  let elem = document.querySelector("#content");
  console.log(elem);

  // 操作標籤物件
  elem.innerHTML = "新操作";
  elem.className = "text";
  elem.style.fontSize = "30px";
  elem.style.color = "red";
}

【範例:選單變化】

<div>
  <span onclick="changeToAbout();">關於我</span>
  <span onclick="changeToExps();">學經歷</span>
</div>
<hr />
<div id="about">大家好,我是XXX</div>
<div id="exps" style="display: none">我是XX工程師</div>
function changeToAbout() {
  let aboutDiv = document.querySelector("#about");
  let expsDiv = document.querySelector("#exps");
  aboutDiv.style.display = "block";
  expsDiv.style.display = "none";
}

function changeToExps() {
  let aboutDiv = document.querySelector("#about");
  let expsDiv = document.querySelector("#exps");
  aboutDiv.style.display = "none";
  expsDiv.style.display = "block";
}

2.3 事件處理

向指定元素添加事件,然後透過函式去控制該事件,例如點擊按鈕。

<style>

.btn {
  background-color: #ffcccc;
  padding: 5px;
  border-radius: 5px;
  cursor: pointer;
}

<body>

<button
  onclick="console.log('點擊事件');"
  onmouseover="console.log('滑鼠移入');"
  onmouseout="console.log('滑鼠移出');"
  onmousedown="console.log('滑鼠按住');"
  onmouseup="console.log('滑鼠放開');"
>
  點我
</button>
<span
  class="btn"
  onmouseover="over(this);"
  onmouseout="out(this);"
  onmousedown="down(this);"
  onmouseup="up(this);"
  >點我</span
>

<script>

function over(elem) {
  elem.style.backgroundColor = "#ddaaaa";
}
function out(elem) {
  elem.style.backgroundColor = "#ffcccc";
}
function down(elem) {
  elem.style.fontWeight = "bold";
}
function up(elem) {
  elem.style.fontWeight = "normal";
}

2.4 HTTP 通訊協定簡介

  • 超文字傳輸通訊協定 (HTTP) 是全球資訊網的基礎,用於透過超文字連結載入網頁。
  • HTTP 流程:由客戶端(Client)發出請求(Request),伺服器端(Server)接收請求,再將回應(Response)傳送到客戶端。
  • DNS 域名系統(Domain Name System):負責將域名轉換成 IP 位置。

2.5 AJAX 網路連線

【範例:將.json中的內容印出來】

<body>

<button onclick="getData();">連線取得資料</button>
<div id="result"></div>

<script>

function getData() {
  fetch("https://cwpeng.github.io/live-records-samples/data/products.json")
    .then(function (response) {
      return response.json();
    })
    .then(function (data) {
      let result = document.querySelector("#result");
      result.innerHTML = "";
      for (let i = 0; i < data.length; i++) {
        let product = data[i];
        result.innerHTML +=
          "<div>" +
          product.name +
          ", " +
          product.price +
          ", " +
          product.description +
          "</div>";
      }
    });
}

3. JavaScript 深入進階

3.1 箭頭函式

【未使用箭頭函式】

function calculate(max) {
  let result = 0;
  let n = 1;
  while (n <= max) {
    result += n;
    n++;
  }
  return result;
}
let ans1 = calculate(10);
let ans2 = calculate(20);
console.log(ans1, ans2);

【使用箭頭函式】

let calculate = (max) => {
  let result = 0;
  let n = 1;
  while (n <= max) {
    result += n;
    n++;
  }
  return result;
};
let ans1 = calculate(10);
let ans2 = calculate(20);
console.log(ans1, ans2);

【更簡化的箭頭函式】

//  let multiply = (n1, n2) => {
//    return n1 * n2;
//  };
let multiply = (n1, n2) => n1 * n2;
let ans = multiply(3, 4);
console.log(ans);

3.2 解構賦值

3.2.1 陣列解構賦值

【範例:解構前】

let arr = [3, 4, 5];
let d1 = arr[0];
let d2 = arr[1];
let d3 = arr[2];
console.log(d1, d2, d3);

印出結果:

3 4 5

【範例 1】

let arr = [3, 4, 5];
let [d1, d2, d3] = arr;
console.log(d1, d2, d3);

印出結果:

3 4 5

【範例 2】

let arr = [3, 4, 5];
let d1, d2, d3;
[d1, d2, d3] = arr;
console.log(d1, d2, d3);

印出結果:

3 4 5

【範例 3】

let arr = [3, 4, 5, 2];
let d1, d2, d3, d4;
[d1, d2, d3, d4 = 10] = arr;
console.log(d1, d2, d3, d4);

印出結果:

3 4 5 2

【範例:變數資料交換】

let n1 = 3;
let n2 = 4;
[n2, n1] = [n1, n2];
console.log(n1, n2);

印出結果:

4 3

3.2.2 物件解構賦值

【範例:解構前】

let obj = { x: 3, y: 4 };
let x = obj.x;
let y = obj.y;
console.log(x, y);

印出結果:

3 4

【範例 1】

let obj = { x: 3, y: 4 };
let { x, y } = obj;
console.log(x, y);

印出結果:

3 4

【範例 2】

let obj = { x: 3, y: 4, z: 5 };
let x, y, z;
({ x, y, z = 10 } = obj);
console.log(x, y, z);

印出結果:

3 4 5

【範例 3】

let obj = { x: 3, y: 4, z: 5 };
let newX, newY, newZ;
({ x: newX, y: newY, z: newZ = 10 } = obj);
console.log(newX, newY, newZ);

印出結果:

3 4 5

3.2.3 函式的物件參數

【範例:包到 args 物件裡面】

function add(args) {
  console.log(args.n1 + args.n2);
}
add({ n1: 3, n2: 4 });

印出結果:

7

【範例:運用解構賦值】

function add({ n1, n2 }) {
  console.log(n1 + n2);
}
add({ n1: 3, n2: 4 });

印出結果:

7

3.3 其餘運算

3.3.1 運用在解構賦值

【範例:陣列解構賦值】

let [n1, n2, ...data] = [3, 2, 1, 5, 4, 0];
console.log(n1, n2, data);

印出結果:

3 2 (4) [1, 5, 4, 0]

【範例:物件解構賦值】

let { x, y, ...data } = { x: 3, y: 4, z: 5, a: 1, b: 2 };
console.log(x, y, data);

印出結果:

3 4 {z: 5, a: 1, b: 2}

3.3.2 運用在函式參數

【範例】

function add(n1, n2, ...args) {
  console.log(n1, n2, args);
  let total = n1 + n2;
  for (let i = 0; i < args.length; i++) {
    total = total + args[i];
  }
  console.log(total);
}
add(3, 4);
add(5, 6, 1, 2);
add(1, 2, 3, 1, 1);

印出結果:

3 4 []
7
5 6 (2) [1, 2]
14
1 2 (3) [3, 1, 1]
8

3.4 模組

<body>標籤內新增:

<script type="module" src="main.js"></script>

新增main.js文件,內容:

【範例 1】

import echo from "./lib.js";
let name = "hello";
echo(name);

【範例 2】

import echo from "./lib.js";
let name = "hello";
lib.echo("world");
lib.add(3, 4);

新增lib.js文件,內容:

【範例 1】

function echo(msg) {
  console.log(msg);
}
export default echo;

【範例 2】

function echo(msg) {
  console.log(msg);
}
function add(n1, n2) {
  console.log(n1 + n2);
}
export default {
  echo: echo,
  add: add,
};

3.5 模組的輸出、輸入

main.js

【範例:預設輸入】

import abc from "./lib.js";
console.log(abc);

【範例:非預設輸入】

import { data } from "./lib.js";
import abc, { data, obj } from "./lib.js";
console.log(data);
console.log(obj);

【範例:彈性】

import { multiply } from "./lib.js";
multiply(3, 4);
multiply(-2, 2);
import math from "./lib.js";
math.add(3, 4);
math.multiply(-3, 4);

lib.js

【範例:預設輸出】

let x = "hello";
export default x;

【範例:非預設輸出】

let x = "hello";
let data = [5, 6, 7];
let obj = { x: 10, y: 2 };
// export { data, obj };
export { x as default, data, obj };

【範例:彈性】

let add = function (n1, n2) {
  console.log(n1 + n2);
};
let multiply = function (n1, n2) {
  console.log(n1 * n2);
};
let math = {
add: add,
multiply: multiply,
};
export default math;
export (add, multiply);

3.6 Proxy 代理物件

【範例】

let data = {
  price: 100,
  count: 5,
};

let proxy = new Proxy(data, {
  get: function (target, property) {
    // console.log("代理的目標物件", target);
    // console.log("取得的屬性名稱", property);
    // return "屬性對應的資料";
    if (property === "total") {
      return target.price * target.count;
    } else {
      return target[property];
    }
  },
});

// 使用代理物件,取得物件屬性資料
console.log("總價", proxy.total);
console.log("單價", proxy.price);

3.7 淺拷貝、深拷貝

3.7.1 淺拷貝

淺拷貝是拷貝到第一層。

【範例】

let a = [0, 1, { x: 2, y: 3 }]; // 兩層的物件結構
let b = [...a];

b[0] = 10;
console.log(a[0]); // 不會影響,印出0

b[2].x = 20;
console.log(a[2].x); // 會影響,印出20

從上述得知,由於淺拷貝的關係,不會影響到a[0]的印出結果;但第二層不會被拷貝,所以不會印出第二層中的2,而是印出20

3.7.2 深拷貝

深拷貝是全部拷貝。

【範例】

let a = [0, 1, { x: 2, y: 3 }];
let str = JSON.stringify(a);
let b = JSON.parse(str);

b[2].x = 20;
console.log(a[2].x); // 不會影響,印出2