JavaScript非同步程式設計與回呼函式(Callbacks)

JavaScript默認是同步的,並且是單線程的。這意味著程式碼無法創建新的線程並且並行運行。了解一下非同步程式碼的含義以及它是什麼樣子。 程式語言中的非同步性 JavaScript 回呼函式 處理回呼函式中的錯誤 回呼函式的問題 回呼函式的替代方案 程式語言中的非同步性 電腦的設計使其成為非同步的。 非同步意味著事情可以獨立於主程式流程發生。 在現代消費者電腦中,每個程式運行一段特定的時間片段,然後停止執行,以讓其他程式繼續執行。這個循環運行得非常快,我們認為我們的電腦同時運行許多程式,但這只是一種幻覺(除了在多處理器計算機上)。 程式內部使用中斷,這是發送給處理器以引起系統注意的信號。 我不打算深入探討這方面的內部細節,只是讓你記住,程式是非同步的很正常,它們在等待時會暫停執行,並且電腦可以在此期間執行其他任務。當程式在等待網絡響應時,它無法阻止處理器停止執行。 通常,程式語言都是同步的,一些語言提供了一種處理非同步的方式,可以在語言本身或通過函式庫中進行處理。C、Java、C#、PHP、Go、Ruby、Swift、Python等都是默認同步的。有些語言通過使用線程來處理非同步,而線程則產生新的進程。 JavaScript JavaScript默認是同步的,並且是單線程的。這意味著程式碼無法創建新的線程並且並行運行。 程式碼按照順序一行行執行,例如: const a = 1 const b = 2 const c = a * b console.log(c) doSomething() 然而,JavaScript誕生於瀏覽器中,最初的作用是響應用戶操作,比如onClick、onMouseOver、onChange、onSubmit等等。它如何在同步程式模型下實現這一點呢? 答案就在它的環境中。瀏覽器提供了一種處理此類功能的方式,它提供了一組API。 最近,Node.js引入了一個非阻塞的I/O環境,用於擴展此概念到文件訪問、網絡請求等等。 回呼函式 你無法知道用戶何時會點擊一個按鈕,所以你要做的是,為點擊事件定義一個事件處理函式。這個事件處理函式接受一個函式作為參數,在事件觸發時將調用該函式。 document.getElementById('button').addEventListener('click', () => { //當按鈕被點擊時執行 }) 這就是所謂的回呼函式。 回呼函式就是一個簡單的函式,它作為值傳遞給另一個函式,並且只有在事件發生時才會被執行。我們之所以能夠做到這一點,是因為JavaScript提供了一級函式的功能,這些函式可以被賦值給變量並且可以傳遞給其他函式(稱為高階函式)。 通常會將所有的用戶端代碼包裝在window對象上的load事件監聽器中,只有在頁面準備好時才會運行回呼函式: window.addEventListener('load', () => { //視窗已加載 //執行你想做的事情 }) 回呼函式無處不在,不僅僅在DOM事件中使用。 一個常見的例子是定時器: setTimeout(() => { //2秒後執行 }, 2000) XHR請求也接受回呼函式,這個例子中通過將一個函式賦值給一個屬性,在特定事件發生時調用該函式(在此例中,是請求狀態發生改變): const xhr = new XMLHttpRequest() xhr.onreadystatechange = () => { if (xhr....

JavaScript類型轉換(型別轉換)

了解 JavaScript 類型轉換的基礎知識 即使 JavaScript 是一種弱類型語言,您可能需要將值從一種類型轉換為另一種類型。 在 JavaScript 中,我們有以下原始類型: Number String Boolean Symbol 以及對象類型: Object (還有 null 和 undefined,但從它們轉換到其他類型沒有意義) 例如,您可能想要進行以下轉換: 將數字轉換為字符串 將字符串轉換為數字 將字符串轉換為布爾值 將布爾值轉換為字符串 等等。 以下是您可以使用的技巧將一種類型轉換為另一種類型。我將涵蓋最常見的情況。 轉換為字符串 通常,從任何值轉換為字符串通常只需在任何值上調用 toString() 方法,JavaScript 將創建與該類型對應的字符串值。或者,您可以將任何值傳遞給 String() 全局函數。 從數字轉換為字符串 使用 String 全局函數,或者使用數字類型的 toString() 方法: String(10) //"10" (10).toString() //"10" 從布爾值轉換為字符串 使用 String 全局函數或布爾類型的 toString() 方法: String(true) //"true" true.toString() //"true" String(false) //"false" false.toString() //"false" 從日期轉換為字符串 使用 String 全局函數或日期類型的 toString() 方法: String(new Date('2019-01-22')) //"Tue Jan 22 2019 01:00:00 GMT+0100 (Central European Standard Time)" (new Date('2019-01-22'))....

JavaScript食譜

JavaScript食譜包含許多有用的教學文章,解釋如何在JavaScript中執行常見的操作。 注意:此文檔將不斷更新。隨著時間的推移,此文章將填滿大量有用的教學內容。 字串 如何將JavaScript字串中的首個字母轉成大寫 如何在JavaScript中檢查字串是否包含子字串 如何在JavaScript中替換字串的所有出現 如何將字串轉換為數字 如何在JavaScript中創建多行字串 如何在JavaScript中檢查字串是否以另一個字串開頭 數字 如何去掉JavaScript數字中的前導零 如何將數字格式化為貨幣值 如何在JavaScript中生成兩個數字之間的隨機數 日期 如何在JavaScript中獲取當前的時間戳記 物件 如何從JavaScript物件中刪除屬性 如何檢查JavaScript物件 如何深度克隆JavaScript物件 如何檢查JavaScript物件屬性是否為未定義 如何合併兩個JavaScript物件 如何在JavaScript中動態訪問物件的方法 如何使用解構語法處理數組和物件 如何計算JavaScript物件中的屬性數量 如何列出JavaScript物件的所有方法 數組 如何從JavaScript數組中刪除項目 如何在JavaScript數組中追加項目 如何在JavaScript中使用值初始化新數組 如何在Array.map()中使用Async和Await 如何清空JavaScript數組 如何按屬性值對JavaScript物件數組進行排序 如何從JavaScript數組中獲取一組物件的唯一屬性 函數 如何在JavaScript中設置默認參數值 循環 如何在JavaScript的for-of循環中獲取迭代的索引

Johnny Five,如何與LCD屏幕配合工作

本文是Johnny Five系列文章的一部分。請參閱第一篇文章。 LCD屏幕是一個很酷的組件,因為我們可以用它在各種不同的創意項目中使用。 這個我拿到的是名叫1602A的。 它有16個引腳。我按照以下方式連接它: 引腳1連接到0V 引腳2連接到控制背光的電位器 引腳3連接到5V 引腳4連接到Arduino的引腳7 引腳5連接到0V 引腳6連接到Arduino的引腳8 引腳11連接到Arduino的引腳9 引腳12連接到Arduino的引腳10 引腳13連接到Arduino的引腳11 引腳14連接到Arduino的引腳12 引腳15連接到5V 引腳16連接到0V 電位器有3個腳。中間的腳連接到LCD屏幕,左邊的腳連接到0V,右邊的腳連接到5V。 接線就完成了。 創建一個新的lcd.js文件並載入以下代碼: const { Board, LCD } = require("johnny-five"); const board = new Board(); board.on("ready", function() {}); 現在從LCD類初始化一個新的LCD對象。 確切的初始化程序取決於所使用的顯示器的類型。在我的情況下,是這樣的: const lcd = new LCD({ pins: [7, 8, 9, 10, 11, 12] }); 最後,調用print()方法顯示一個字符串: const { Board, LCD } = require("johnny-five"); const board = new Board(); board.on("ready", function() { const lcd = new LCD({ pins: [7, 8, 9, 10, 11, 12] }); lcd....

Johnny Five,如何點亮一個LED

學習如何使用JavaScript與電子設備進行通訊 本文是Johnny Five系列的一部分。請先看第一篇文章。 首先創建一個文件夾並初始化npm: npm init -y 然後在本地安裝Johnny Five: npm install johnny-five 現在創建一個名為app.js的文件,內容如下: const { Board, Led } = require("johnny-five") const board = new Board() board.on("ready", () => { const led = new Led(13) led.blink() }) 這個程式通過調用new Board()來初始化一個新的開發板。 當開發板準備就緒時,board對象會觸發ready事件,我們可以在回調函數中執行我們的應用程序。 在這個簡單的例子中,我們通過初始化一個新的Led對象在引腳13上初始化一個新的LED,然後使其閃爍(不斷開關)。 Led對象和Board對象是Johnny Five庫提供的許多功能之一。 Arduino Uno開發板上的13號引腳是連接到內置LED的引腳。 現在運行node app.js來執行程序: 你應該可以看到LED不斷開關! 你也可以通過將負極引腳連接到GND(0V),將正極引腳連接到引腳13,以連接一個真實的LED: 注意我使用了一個電阻器來限制LED通過的電流量。 要停止運行程序,請按兩次ctrl-C:

JSON介紹

JSON是一種儲存和交換資料的優良格式,廣泛用於JavaScript但不僅限於此-了解一切有關它的知識! JSON是一種文件格式,用於儲存和交換資料。 資料以鍵值對的形式儲存。 JSON格式易於人類閱讀,非常適合手動編輯。 這是一個JSON字符串的例子: { "name": "Flavio", "age": 35 } 從這個小片段中,你可以看到鍵被包裹在雙引號中,冒號分隔鍵和值,值可以是不同的類型。 鍵值對之間用逗號分隔。 在JSON文件中,間距(空格、制表符、換行)不重要。上述示例等同於 {"name": "Flavio","age": 35} 或 {"name": "Flavio","age": 35} 但像一直以來,格式良好的資料更容易理解。 JSON誕生於2002年,由於易於使用和靈活性而迅速流行起來,儘管它起源於JavaScript,但很快就擴展到其他編程語言中。 它在ECMA-404標準中有所描述。 JSON字符串通常存儲在.json文件中,並以application/json的MIME類型在網絡上傳輸。 數據類型 JSON支援一些基本數據類型: Number:不帶引號的任意數字 String:用引號包裹的任意字符集 Boolean:true或false Array:用方括號包裹的值列表 Object:用大括號包裹的鍵值對集合 null:表示空值的單詞null 其他任何數據類型都必須被序列化為字符串(然後反序列化)才能存儲在JSON中。 在JavaScript中編碼和解碼JSON ECMAScript 5於2009年在JavaScript標準中引入了JSON對象,該對象提供了JSON.parse()和JSON.stringify()方法,此外還有其他功能。 在JavaScript程序中使用JSON字符串之前,必須將其解析並轉換為JavaScript可以使用的數據。 JSON.parse()將JSON字符串作為參數,並返回包含解析後JSON的對象: JSON.parse(string) JSON.stringify()將JavaScript對象作為參數,並返回表示其為JSON的字符串: JSON.stringify(object) JSON.parse()還可以接受可選的第二個參數,稱為解析器函數。您可以使用它來進行解析並執行任何自定義操作: JSON.parse(string, (key, value) => { if (key === 'name') { return `Name: ${value}` } else { return value } }) 嵌套對象 您可以使用嵌套對象來組織JSON文件中的數據: { "name": { "firstName": "Flavio", "lastName": "Copes" }, "age": 35, "dogs": [ { "name": "Roger" }, { "name": "Syd" } ], "country": { "details": { "name": "Italy" } } } 用於處理JSON的在線工具...

Moment.js 教學

Moment.js 是一個在 JavaScript 中處理日期非常有幫助的庫。 Moment.js 是一個非常棒的 JavaScript 库,可以幫助你處理日期,不管是在瀏覽器上還是在 Node.js 中都可以使用。 這篇文章旨在解釋這個庫的基本知識和最常見的用法。 安裝 你可以直接在你的頁面中使用 script 標籤引入它,從 unpkg.com: <script src="https://unpkg.com/moment" /> 或者使用 npm 安裝: npm install moment 如果你使用 npm 安裝,需要用 import 引入這個包(使用 ES 模块): import moment from 'moment' 或者用 require 引入它(使用 CommonJS): const moment = require('moment') 獲取當前日期和時間 const date = moment() 解析日期 你可以通過傳遞一個字符串給 moment 對象來初始化它。 const date = moment(string) 它可以接受任意字符串,按照以下順序解析: ISO 8601 RFC 2822 日期時間格式 Date 對象接受的格式 ISO 8601 絕對是最方便的。這是一個格式參考: 格式 意義 範例 YYYY 4 位數年份 2018 YY 2 位數年份 18 M 2 位數月份,忽略前導 0 7 MM 2 位數月份 07 MMM 3 字母月份名稱 Jul MMMM 完整的月份名稱 July dddd 完整的星期名稱 Sunday gggg 4 位數年份的星期 2018 gg 2 位數年份的星期 18 w 不帶前導零的一年中的星期數 18 ww 帶有前導零的一年中的星期數 18 e 星期的第幾天,從 0 開始 4 D 2 位數的日期,忽略前導 0 9 DD 2 位數的日期 09 Do 帶序數的日期 9th T 表示時間部分的開始 HH 2 位數的小時(24 小時制),從 0 到 23 22 H 2 位數的小時(24 小時制),從 0 到 23,不帶前導 0 22 kk 2 位數的小時(24 小時制),從 1 到 24 23 k 2 位數的小時(24 小時制),從 1 到 24,不帶前導 0 23 a/A 上午 或者 下午 下午 hh 2 位數的小時(12 小時制) 11 mm 2 位數的分鐘 22 ss 2 位數的秒數 40 s 2 位數的秒數,不帶前導零 40 S 1 位數的毫秒數 1 SS 2 位數的毫秒數 12 SSS 3 位數的毫秒數 123 Z 時區 +02:00 x 毫秒級的 UNIX 時間戳 1410432140575 設置日期 格式化日期 當你想要輸出普通的 JavaScript Date 對象的內容時,你只有很少的選擇來確定格式。你只能使用內置的方法,使用它們來組成你想要的日期。...

node_modules 資料夾大小不是問題,反而是一個特權

關於 node_modules 資料夾大小辯論的我的想法 我曾對於 node_modules 資料夾的大小感到懊惱。一個 JavaScript 應用程式怎麼可能在沒有我加入任何一行程式碼的情況下就有100、200MB的大小呢?我只是執行 npx create-react-app todolist,然後下載了218.7MB的東西!(我現在剛剛檢查了一下,這是真的數字)。 每當你思考 node_modules 的大小時,請想想我們程式開發人員投入的無數工時。 這是完全開源的軟體,是你可以檢視和學習的軟體。它是由世界各地的程式開發人員和公司慷慨捐贈的。它是一個全球性的努力,某人將它變得非常簡單好用。首先是 npm 這個工具,接著才是 npm 公司。 我們都同意將自己的程式碼發布到他們的伺服器上,人們在上面進一步建立了其他東西,直到我們得到了快速入門工具(如 create-react-app 或 Vue CLI 等),可以免費獲得大量功能。 在 TB 級快速儲存的時代,200MB 的大小算太大嗎? 請記住,在這個大小中,絕大多數是測試、文件等等。而且剩下的程式碼絕大多數只會在開發環境中使用。這並不意味著你會將一個200MB的應用程式提供給用戶,我認為這一點是深入人心的。 我以 create-react-app 為例,那 200MB 中有些什麼? 首先,create-react-app 包含了: 編譯器 (Babel) 打包工具 (Webpack) 程式碼壓縮工具 程式碼檢查工具 (ESLint) 樣式流程工具 (SCSS) 具有熱重載功能的開發伺服器 測試執行工具 (Jest) 如果你想要開發 Mac 或 iPhone 應用程式,你必須安裝蘋果提供的 IDE,即 Xcode。Xcode 的大小(等一下……)幾乎是 14GB。那是 node_modules 的 70 倍大小。確實,我們在比較兩件不同的事物,但 node_modules 包含了你開始編寫程式碼所需的一切。你可以搭配大小為 200MB 的 VS Code 或大小為 30MB 的 Sublime Text 使用,都沒關係,並不是必須的(而你卻無法在沒有 Xcode 的情況下創建 iOS/macOS 應用程式)。...

Node.js 流

學習流的作用以及為什麼它們如此重要以及如何使用它們。 什麼是流 為什麼使用流 流的一個例子 pipe() 基於流的 Node.js API 不同類型的流 如何創建可讀流 如何創建可寫流 如何從可讀流中獲取數據 如何將數據發送到可寫流 告訴可寫流您已經結束寫入 什麼是流 流是 Node.js 應用程序的基本概念之一。它們是一種以高效方式處理讀取/寫入文件、網絡通信或任何類型的端到端信息交換的方法。 流不是 Node.js 獨有的概念。它們在數十年前引入了 Unix 操作系統,程序可以通過管道運算符(|)相互交互地傳遞流。 例如, 在傳統的方式中,當您要求程序讀取一個文件時,文件被從頭到尾讀入內存,然後進行處理。 使用流,您可以分塊讀取它,處理其內容,而無需將其全部保留在內存中。 Node.js 的 stream 模塊 提供了所有流 API 的基礎。 為什麼使用流 流主要提供了兩個優勢,與其他數據處理方法相比: 內存效率:您不需要在能夠處理數據之前將大量數據加載到內存中。 時間效率:只要有數據可用,開始處理數據所需的時間遠小於等到整個數據有效負載可用時的時間。 流的一個例子 一個典型的例子是從磁盤讀取文件。 使用 Node fs 模塊,當建立一個新的連接到您的 HTTP 服務器時,您可以讀取一個文件並在 HTTP 上提供它: const http = require('http'); const fs = require('fs'); const server = http.createServer(function (req, res) { fs.readFile(__dirname + '/data.txt', (err, data) => { res.end(data); }); }); server....

Node.js 簡介

這篇文章是關於 Node.js 的入門指南,Node.js 是一個運行在伺服器端的 JavaScript 執行環境。Node.js 是建立在 Google Chrome V8 JavaScript 引擎之上,主要用於建立網頁伺服器,但不僅限於此。 概述 [Node.js 的最佳特性](#node.js 的最佳特性) 快速 簡單 JavaScript V8 異步平台 大量的函式庫 [一個 Node.js 應用程式範例](#一個 Node.js 應用程式範例) [Node.js 框架和工具](#node.js 框架和工具) Node.js 是一個在伺服器上運行的 JavaScript 執行環境。 Node.js 是開源的、跨平台的,自從在2009年推出以來,它已經變得非常流行,現在在網頁開發中扮演著重要的角色。如果以 GitHub 上的 stars 數量作為流行度指標,擁有58000+ stars就意味著非常受歡迎。 Node.js 運行 V8 JavaScript 引擎,該引擎是 Google Chrome 的核心,而 Node.js 可以利用使 Chrome JavaScript 執行時非常高速的工程師的工作,這使得 Node.js 可以受益於巨大的性能改進和即時編譯。由於這一點,運行在 Node.js 中的 JavaScript 代碼可以非常高效。 Node.js 的應用程式由單個進程運行,不為每個請求創建新的線程。Node.js 的標準庫提供了一組異步 I/O 原語,可以防止 JavaScript 代碼阻塞,通常情況下 Node.js 的庫都是使用非阻塞的範例來編寫,使得阻塞行為成為異常而不是正常行為。 當 Node....