部落格

不定期分享技術文章

  • article-Day14 同步&非同步(Synchronous & Asynchronous)

    2023/9/28

    React JavaScript
    Day14 同步&非同步(Synchronous & Asynchronous)

    就中文來看這兩種的意思其實相當容易被搞混的,我自己常常在閱讀文章時也很常莫名的被這兩個名詞搞昏頭。所以我會直接用例子來幫助記憶接說明如下:

    1. 同步(Synchronous):就是 A 處理完再處理再處理 C

      A -> B -> C->

    2. 非同步(Asynchronous):就是可以同時處理 ABC

      –>A
      |
      –>B
      |
      –>C

    那話又說回來 JavaScript 是屬哪一種呢?

    引用 MDN 的定義

    Javascript 基本上是一個同步性的、阻塞的,且是跑在單一執行緒的程式語言,也就是在同一時間只能執行一個操作。但是瀏覽器所定義的函式和 API 允許我們註冊一個不該被同步執行的函式,且這個函式應該在某些事件發生時需要非同步的被呼叫(到達指定的時間、使用者透過滑鼠互動,或者取得透過從網路所取到的資料)。這代表你可以讓你的程式碼在同時間做一些事情而不需暫停或阻塞你的主執行緒。

    簡單來說,MDN 很明確的定義 javascript 是一個同步性的語言,但可以處理或是說可以執行非同步的方法。下面的例子可以說明:

    console.log("registering click handler");
    
    button.addEventListener("click", () => {
      console.log("get click");
    });
    
    console.log("all done");
    

    PS:上述是簡化後的例子,真的需要執行的話如下網址:
    https://codepen.io/Hsienlu/pen/PoXevrJ

    可以發現實際在執行的時候,”all done”並不會等到”get click”被觸發時才會出現,而是會直接執行,所以才會說雖然 JavaScript 是同步性的語言,但可以處理需要非同步處理的事情。

    但是,非同步的事情常常會具有不確定性存在(不知道哪個會先發生哪個會後發生),於是就有了一些處理同步和非同步的方法,這些方法明天會繼續介紹。

    參考資料

    1.非同步的 JavaScript 介紹

  • article-Day13 JavaScript 模組(Modules)

    2023/9/27

    React JavaScript
    Day13 JavaScript 模組(Modules)

    模組系統的概念大致上分兩種寫法,CommonJS 和 ESM 其引入方式的差異分別是 require 和 import,今天會著重在 ESM 的寫法。

    模組的概念其實在 React 框架已經不知不覺地被頻繁的使用了,像是最常見的 hook–useState 就是在引入模組的時候才做使用的,又或是元件的寫法也是由模組系統做延伸。

    模組基本上可以分為兩種匯出方式命名匯出(Named Exports)和預設匯出(Default Exports),其對應的匯入方式也有所差別

    命名匯出(Named Exports)

    命名匯出使用關鍵詞 ==export==+==要輸出東西的名稱==,好處是在於同一個檔案能使用很多個匯出

    export function add(a, b) {
      return a + b;
    }
    
    export function subtract(a, b) {
      return a - b;
    }
    

    其對應的匯入方式如下,import 模組,然後從哪裡 from

    import {add, subtract} from "./math";
    
    console.log(add(5, 3)); // 輸出: 8
    console.log(subtract(10, 4)); // 輸出: 6
    

    預設匯出(Default Exports)

    1.預設匯出使用關鍵詞 ==export default==,特別注意同一個檔案只能有一個預設匯出

    export default function add(a, b) {
      return a + b;
    }
    

    其對應的匯入方式如下,與上述雷同差別在於針對單一輸出的模組所以可以不用大括弧{}

    import add from "./math";
    
    console.log(add(5, 3)); // 輸出: 8
    

    總結

    以下簡單整理一個表格,我自己會認為不太需要花時間去記憶,因為用久自然就熟了,而且現在套件的幫助下其實也比較不太會在這方面出差錯。

    特性 命名匯出出 (Named Exports) 預設匯出 (Default Export)
    匯出方式 可以匯出多個具名功能 只能匯出一個默認功能
    匯入的語法 使用 {} 語法進行匯入 直接使用模組名稱進行匯入

  • article-Day12 其餘運算子 & 展開運算子(Spread Operator & Rest Operator)

    2023/9/26

    React JavaScript
    Day12 其餘運算子 & 展開運算子(Spread Operator & Rest Operator)

    接著就是傳說中的…了,正式名稱為其餘運算子和展開運算子,這個點點點同時具有兩種功能,也是在 React 中被廣泛使用的,接下來依序介紹

    1.其餘運算子

    其實在昨天的文章中以已經有先使用這個與法了,這個功能的作用顧名思義就是可以接剩下來的值
    引用 MDN 的說法:

    “這個語法可以讓我們表示==不確定數量的參數==,並將其視為一個==陣列==。”

    在實際用途會在兩個地方,一個是在解構賦值,其實昨天的文章已經有偷偷用到了;另一個是在傳入不確定量參數的時候。

    (1) 解構賦值
    …rest 的作用就是用來接解構賦值命名完變數剩下來的值

    let array = [1, 2, 3, 4, 5];
    let a, b, rest;
    [a, b, ...rest] = array;
    console.log(a); //輸出:1
    console.log(b); //輸出:2
    console.log(rest); //輸出:3,4,5
    

    (2) 傳入不確定量的參數
    這裡直接舉一個情境,我想要傳入一列數字但==不確定==有多少數字,並設計一個函示找出最小值,範例如下:

    function findMin(...Array) {
      //^^^^^^^^傳入不確定參數的量
      console.log(Array);
      let minValue = Math.min(...Array);
      //^^^那這個點點點又是什麼呢?
      console.log(minValue);
    }
    findMin(1, 2, 3, 4, 5);
    

    相信大家都有注意到 Mata.min 的…又是什麼呢?這其實跟昨天文章提到的解構有關。

    (3) 解構其餘參數
    當初在學這個時候,還沒有想到這個點點點有這樣神奇的功能,直接引用 MDN 的定義

    其餘參數可以被解構,換句話說,可以把這個陣列解開,並將各個元素取出成為個別的變數。請參考解構賦值。

    其實這個功能我認為跟下面準備要提的展開運算子其實蠻相似的,只是 MDN 有另外再把它定義出來。
    重點就是,其餘參數追根究柢就是一個==陣列==需要把陣列展開來,所以其實如果上述範例改成下面這個例子是會跑出 NaN 的,因為 Math.min()沒辦發接受傳入純陣列

    function findMin(...Array) {
      //^^^^^^^^傳入不確定參數的量
      console.log(Array);
      let minValue = Math.min(Array); //輸出:NaN
      //^^^那這個點點點又是什麼呢?
      console.log(minValue);
    }
    findMin(1, 2, 3, 4, 5);
    

    2.展開運算子

    MDN 定義

    展開運算子, 可以在函數調用/陣列構造時,將陣列表達式或者 string 在語法層面展開
    其實講的簡單一點就是把一個陣列的中刮弧拿掉的意思,後還有一個特殊功能就是可以對類陣列進行展開。

    (1)陣列展開
    有名的淺拷貝就是一個經典的例子,如下:

    const array = [1, 2, 3, 4];
    const newArray = [...array];
    console.log(array);
    console.log(newArray);
    //上述兩個會是名稱不一樣,但是內容一模一樣的陣列。
    

    其實在使用上,我會認為不太需要去區分的太仔細,或是刻意去記憶,因為其實本身在使用的情境上去做區分,所以多去使用它自然而然的就可以對這兩類與法做出一些區別。

    參考資料

    1.MDN 其餘運算子

    2.MDN 展開運算子

  • article-Day11 解構賦值(Destructuring assignment)

    2023/9/25

    React JavaScript
    Day11 解構賦值(Destructuring assignment)

    解構賦值是 ES6 新增的語法,根據 MDN 的說法解構賦值 (Destructuring assignment) 語法是一種 JavaScript 運算式,可以把陣列或物件中的資料解開擷取成為獨立變數。
    簡單來說就是解構賦值是一種專門針對陣列或是物件的運算式,作用是把裡面的資料存成獨立變數。

    1.陣列的解構賦值
    基本寫法範例如下,=就像是一面鏡子==依序==對照著兩邊,下面範例示範了 2 個點
    (1)用 a 和 b 對照著 array 中的 1 和 2
    (2)用…rest 對照著剩下的值

    let array = [1, 2, 3, 4, 5];
    let a, b, rest;
    [a, b, ...rest] = array;
    console.log(a); //輸出:1
    console.log(b); //輸出:2
    console.log(rest); //輸出:3,4,5
    

    2.物件的解構賦值

    在 React 中物件的解構賦值很常用在 props 的參數傳遞,最單純直接的用法就是{屬性名稱},有點像陣列的物件取值那樣,也可以賦予新的變數名稱,範例如下
    (1) 取值:把屬性名稱解構成新的變數並帶入原本的屬性值

    const person = {
      name: "John",
      age: 30,
      isStudent: false,
    };
    
    const {name, age} = person;
    console.log(name);
    console.log(age);
    

    (2) 賦予變數名稱:利用鏡射的方式讓物件中的屬性值有了新的變數名稱

    const person = {
      name: "John",
      age: 30,
      isStudent: false,
    };
    
    const {
      name: AAA,
      age: BBB,
      isStudent: CCC,
    } = {name: "John", age: 30, isStudent: false};
    console.log(AAA);
    console.log(BBB);
    console.log(CCC);
    

    **(3) 搭配函式傳入引數,再傳入引數為物件時(常見在 React props 中),可以利用解構賦值,讓語法更為簡潔

    const person = {
      name: "John",
      age: 30,
      isStudent: false,
    };
    
    const helloFunction = ({name}) => {
      console.log(`hello, ${name}`);
    };
    helloFunction(person);
    

    當使用解構賦值(Destructuring Assignment)時,儘管它不是絕對必要的,但確實可以使您的程式碼更加簡潔、易讀,尤其在 React 中傳遞 props 時,這種做法很常見,而且也被廣為使用。

    參考資料

    MDN 解構賦值

  • article-Day 10 物件(Object)

    2023/9/24

    React JavaScript
    Day 10 物件(Object)

    在前端這個花花綠綠的世界,物件是一個傳遞資料很重要的形式,大家熟悉的 json 檔,裡面大部分都是由各種陣列和物件所構成的,所以身為一個前端框架,怎麼樣處理物件也是需備知道的。

    物件的特性

    1.被大括弧包起來 2.裡面是由屬性組成而屬性是由屬性名稱和屬性值組成,如果有學過 PHP 的關聯式陣列的話,感覺有點像是鍵和鍵值。 3.屬性值可以是數字、字串、陣列、甚至其他物件或函數這裡會稱其為方法,
    實際物件的樣子如下

    const person = {
      name: "John",
      age: 30,
      isStudent: false,
    };
    

    讀取物件的方法

    陣列取值的方法有兩種:

    1.點記法(Dot notation)
    顧名思義就是用.來取值,直接看範例

    const person = {
      name: "John",
      age: 30,
      isStudent: false,
    };
    console.log(person.name); //輸出:John
    

    2.物件陣列取值(Bracket notation)
    在 MDN 又稱括弧記法,只是我覺得陣列取值這個名稱比較生動,其最大的優點是可以利用變數或是運算方法取值,範例如下:
    (1).普通的

    const person = {
      name: "John",
      age: 30,
      isStudent: false,
    };
    console.log(person["name"]); //輸出:John
    

    (2).變數

    let props = "name";
    const person = {
      name: "John",
      age: 30,
      isStudent: false,
    };
    console.log(person[props]); //輸出:John
    

    (3).運算方法:雖然這個範例有點硬要,但我希望還是能盡量簡化範例

    let props1 = "na";
    let props2 = "me";
    const person = {
      name: "John",
      age: 30,
      isStudent: false,
    };
    console.log(person[props1 + props2]); //輸出:John
    

    建立物件的方法

    建立物件的方法有許多種,比較常見的就是直接宣告又稱 Object Literal,還有 new 搭配建構函式,當然 ES6 也有新增的語法糖類別(class)跟 constructor 可以運用

    1. 直接宣告(Object Literal)
    顧名思義就是直接宣告一個物件,範例如下

    //建立物件
    let people = {};
    //新增內容至物件
    people.name = "amy";
    people.age = 18;
    //輸出結果
    console.log(people);
    

    2. new 搭配建構函式
    先建立一個增加物件的函式,然後呼叫函示建立物件

    //增加物件的函式
    function people(name, age) {
      console.log(this);
      this.name = name;
      this.age = age;
    }
    //函示建立物件
    let newPerson = new people("tom", 18);
    console.log(newPerson);
    

    3. class 語法糖
    class 加上 constructor 也可以建立一個物件,範例如下:

    //增加物件的函式
    class People {
      constructor(name, age) {
        this.name = name;
        this.age = age;
      }
    }
    //函示建立物件
    let newPerson = new People("tom", 18);
    console.log(newPerson);
    

    上述是基本的物件的一些特性以及基本的使用方法,至少要先知道是怎麼來的以及怎麼使用,會對之後在 React 上進行資料處理的時候順暢一點。

  • article-Day 9 函式與箭頭函式

    2023/9/23

    React JavaScript
    Day 9 函式與箭頭函式

    函式 function

    在 React 中,會經常使用函數來建立和管理 React 中的各項元件,而 React 架構的網頁實際上又是由個元件組成的,所以在進入 React 之前了解一些 function 的觀念有其必要性存在。

    function 的宣告方法

    大致上比較常用的有下列三種

    第一種:最為常見使用有名稱的函式

    function callName() {
      console.log("Tom");
    }
    callName();
    

    第二種:用變數宣告匿名函式,可以防止 function hoisting 的問題

    let callName = function () {
      console.log("Tom");
    };
    callName();
    

    第三種:用物件

    let name = {
      callName: function () {
        console.log("Tom");
      },
    };
    name.callName();
    

    function 與 return 的特性

    1. 函式必定有回傳值,如果沒有回傳值,值就是 undefined
    function callName() {
      console.log("Tom");
    }
    callName();
    //會出現Tom與undefined
    

    function callName() {
      return "Tom";
    }
    callName();
    //不會出現undefined
    

    1. return 具有中斷函式的特性
    2. return 後方可以加入表達式

    函式預設參數值 function Default parameters

    根據 MDN 的說法”函式預設參數 允許沒有值傳入或是傳入值為 undefined 的情況下,參數能以指定的預設值初始化。”,不過簡單來說就是給一個函式預設的值,範例如下

    function callName(name = "Tom") {
      console.log(`${name}`);
    }
    callName();
    

    IIFE 立即執行函數

    顧名思義就是立即執行函數,雖然有點像廢話,不過就是讓函式在定義的時候馬上執行一次。

    引用 MDN 的說明

    他又稱為 Self-Executing Anonymous Function,是一種常見的設計模式,包含兩個主要部分:
    第一個部分是使用 Grouping Operator () 包起來的 anonymous function。這樣的寫法可以避免裡面的變數污染到 global scope。
    第二個部分是馬上執行 function 的 expression (),JavaScript 引擎看到它就會立刻轉譯該 function。

    其寫法有兩種,
    第一種:第二個小括弧在外面

    (function callName(name = "Tom") {
      console.log(`${name}`);
    })();
    

    第二種:第二個小括弧在裡面

    (function callName(name = "Tom") {
      console.log(`${name}`);
    })();
    

    無論是哪一種就不用還需要額外呼叫函示囉

    箭頭函式 arrow function

    是一種函式的簡寫法,當然與原本 function 的形式還是有些許的不同

    箭頭函式的寫法

    以上面的例子而言寫成箭頭函式的形式如下:

    let callName = () => {
      console.log("Tom");
    };
    

    箭頭函式簡易的寫法

    1.只有一個參數的時候可以不用加箭頭前面的小括號

    let multi = (a) => {
      console.log(a * 2);
    };
    

    2.如果只有一行表達式或是只有回傳一個值可以把大括弧拿掉,但是有這樣寫就意味者自帶 return,所以實際上是省略了{}還有 return

    let multi = (a) => a * 2;
    

    箭頭函式的特性

    1.this 通常指向全域或是說最近的非箭頭函式的 this 值 2.沒有建構函式 3.在 JSX 中可能會看到下面那這種()寫法這是因為已經只有一行的狀況下可以省略掉大括弧,那為什麼可以省略?因為在()為群組運算子 Grouping operator 視為同一行

    const callName = (props) => (
      <div>
        <h1>Tom</h1>
      </div>
    );
    

    引用資料

    MDN 預設參數( Default parameters )
    MDN IIFE