解釋 JavaScript 閉包

輕鬆介紹閉包的主題,這是理解 JavaScript 函數如何運作的關鍵。 如果你曾經在 JavaScript 中寫過函數,你已經使用過閉包了。 這是一個需要理解的重要主題,會對你能做的事情產生影響。 當一個函數被執行時,它是在定義時的作用域中運行,而不是在執行時的狀態中運行。 作用域基本上是一組可見的變數。 一個函數記住了它的詞法作用域,它能夠訪問在父範圍中定義的變數。 簡而言之,一個函數能夠訪問一個完整的變數集合。 讓我馬上舉個例子來澄清這點。 const bark = dog => { const say = `${dog} barked!` ;(() => console.log(say))() } bark(`Roger`) 這將按預期將 Roger barked! 輸出到控制台。 如果你想返回這個動作呢: const prepareBark = dog => { const say = `${dog} barked!` return () => console.log(say) } const bark = prepareBark(`Roger`) bark() 這段代碼也會在控制台上輸出 Roger barked!。 讓我們舉一個最後的例子,它使用 prepareBark 預先設定兩隻不同的狗: const prepareBark = dog => { const say = `${dog} barked!...

設置項目以使用Phaser構建JavaScript遊戲

建立一個現代化的項目,並開始使用Phaser 3構建JavaScript HTML5遊戲 Phaser是一個了不起的平台,它使創建遊戲變得非常簡單,還支持物理引擎。它足夠受歡迎,你可以找到插件和工具來更好地構建遊戲並更快地構建遊戲。 它基於HTML5技術,這意味著您可以通過Web進行遊戲分發,並且如果需要,也可以將其打包為桌面或移動應用程序。 遊戲編程是一個大的主題,在這個介紹中,我想談談基本知識,這些基本知識足以創建簡單的遊戲。 在這個教程中,我想詳細介紹一個最佳設置,以使用Phaser 3構建遊戲。 讓我們在文件夾中使用npm安裝phaser: npm init -y npm install phaser 現在讓我們設置 Parcel 來打包我們的遊戲: npm install -g parcel-bundler 現在創建一個 game.js 文件,內容如下: import Phaser from 'phaser' new Phaser.Game() 現在運行 parcel watch game.js Parcel將在 dist/game.js 文件中生成我們的JavaScript代碼。 現在創建一個 index.html 文件,內容如下: <!DOCTYPE html> <html> <head> <script src="./dist/game.js"></script> </head> </html> 安裝 browser-sync 以運行一個包含這個文件夾內容的HTTP服務器: npm install -g browser-sync 然後運行 browser-sync start --server --files "." 上述命令將監視當前文件夾(和所有子文件夾)中的所有文件的變化,并在端口3000上啟動一個Web服務器,自動打開一個瀏覽器窗口連接到服務器。 每次您更改文件時,瀏覽器將自動刷新。 在我們原型開發遊戲時,這將非常有用。 您現在應該在瀏覽器中看到一個空白屏幕,因為我們初始化了Phaser: import Phaser from 'phaser' new Phaser....

選擇器 API:querySelector 和 querySelectorAll

使用 querySelector 和 querySelectorAll 訪問 DOM 元素。它們接受任何 CSS 選擇器,所以現在您不再受限於僅通過 id 選取元素 介紹 選擇器 API 基本的從 jQuery 到 DOM API 的範例 通過 id 選取 通過 class 選取 通過標籤名選取 更高級的從 jQuery 到 DOM API 的範例 選取多個項目 通過 HTML 屬性值選取 通過 CSS 偽類選取 選取元素的後代 介紹 過去,jQuery 和其他 DOM 函式庫由於提供了一種在頁面上選取元素的簡單方法而大獲成功。傳統上,瀏覽器僅提供了一種選取 DOM 元素的方法 - 通過其 id 屬性,使用 document 物件提供的 getElementById() 方法。 選擇器 API 自 2013 年以來,選擇器 API 允許您使用兩種更有用的方法: document.querySelector() document.querySelectorAll() 據 caniuse.com 告訴我們,它們可以安全使用,並且除所有其他現代瀏覽器外,甚至在 IE9 上也完全支持,因此除了需要支持 IE8(它只有部分支持)和更低版本之外,沒有理由不使用它們。...

配置 VS Code

如何從零配置 VS Code,使其成為完美的 JavaScript 開發工具 最近我買了一台新的 Mac(MacBook Air),需要安裝全新的 VS Code,所以我花了點時間記錄下來,把我的編碼體驗與使用的舊 MacBook Pro 相同,該筆記本已經使用了長達 9 年的時間。 還可以查看我的 VS Code 介紹 文章 以下是我所做的事情: 我安裝了 Fira Code 並將其設置為我的字體 我將制表符大小設置為2(這是我的習慣)。空格。2個空格。 我將 **/node_modules 添加到排除文件列表中,以防止它們顯示在文件列表中 我啟用了“粘貼時格式化”和“保存時格式化”功能 啟用了字體連接功能 停用了縮略圖功能 啟用了“修剪末尾空格”功能 我安裝了 Sublime Text 按鍵映射插件。這對於顯示/隱藏側邊欄,關閉文件等提供了快捷鍵,例如 cmd-K cmd-B。 接下來,我安裝了一些主題。這取決於你的個人喜好。我喜歡在以下主題之間切換: Palenight 主題 Nostromo Night Owl Ayu 然後我安裝了以下擴展: Prettier IntelliSense for CSS class names Intent 4-to-2 ESLint Duplicate action Bracket Pair Colorizer 2 Babel ES6/ES7 ES7 React/Redux/GraphQL/React-Native snippets TODO Highlight 這是開始使用 JavaScript 和 React 的好套件集合。...

高效加載JavaScript:使用defer和async

在HTML頁面中加載腳本時,你需要小心,以避免影響頁面的加載性能。根據你在HTML頁面中添加腳本的位置和方式,將影響加載時間。 位置的重要性 async和defer 性能比較 沒有defer或async,在head中 沒有defer或async,在body中 使用async,在head中 使用defer,在head中 阻塞解析 阻塞渲染 domInteractive 保持順序 告訴我最好的方法 在HTML頁面中加載腳本時,你需要小心,以避免影響頁面的加載性能。 傳統上,腳本是以以下方式包含在頁面中: <script src="script.js"></script> 當HTML解析器找到這行代碼時,將發出請求以獲取腳本並執行它。 一旦此過程完成,解析可以繼續,並分析頁面的其餘內容。 正如你可以想像的,此操作對頁面的加載時間產生了巨大影響。 如果腳本加載時間比預期的要長,例如如果網絡速度較慢,或者如果你使用的是移動設備且連接不穩定,訪問者可能會看到一個空白頁面,直到腳本加載並執行完成。 位置的重要性 當你初學HTML時,你被告知腳本標籤位於<head>標籤中: <html> <head> <title>標題</title> <script src="script.js"></script> </head> <body> ... </body> </html> 正如之前所說,當解析器找到這行代碼時,它將獲取腳本並執行它。 然後,在完成這個任務之後,它繼續解析body。 這樣做是不好的,因為會引入很多延遲。解決這個問題的一個常見解決方案是將script標籤放在頁面底部,即在結束的</body>標籤之前。 這樣做可以在頁面已經解析和加載完成之後加載和執行腳本,這對於不支持HTML的兩個相對新的功能(async和defer)的舊瀏覽器來說是一個巨大的改進。 如果你需要支持不支持async和defer的舊瀏覽器,這是你可以做的最好的事情。 async和defer async和defer都是布爾屬性。它們的使用方式類似: <script async src="script.js"></script> <script defer src="script.js"></script> 如果你同時指定了這兩個屬性,對於現代瀏覽器來說,async的優先級更高,而對於支持defer但不支持async的舊瀏覽器,則會回退到使用defer。 有關支持情況的詳細信息,可以參考 caniuse.com 中的 async https://caniuse.com/#feat=script-async 和 defer https://caniuse.com/#feat=script-defer 只有在將腳本放在頁面的head部分時,這些屬性才有意義,如果將腳本放在上面看到的body底部,則這些屬性將無效。 性能比較 沒有defer或async,在head中 以下是一個在head部分中未使用defer或async的腳本加載方式: 解析過程在獲取腳本並執行之前暫停,腳本執行完成後解析繼續。 沒有defer或async,在body中 以下是一個在body標籤結束之前並未使用defer或async的腳本加載方式: 解析過程不會暫停,並且腳本在解析完成之後被獲取並執行。解析在腳本甚至下載之前完成,因此頁面在之前的示例中更早地顯示給用戶。 使用async,在head中 以下是一個在head標籤中使用async的腳本加載方式: 腳本異步獲取,當腳本準備好時,HTML解析將暫停以執行腳本,然後繼續解析。 使用defer,在head中 以下是一個在head標籤中使用defer的腳本加載方式: 腳本異步獲取,並且僅在HTML解析完成後才執行。 解析完成的方式與將腳本放在body標籤結束時相同,但是腳本執行的時間總體上更早,因為腳本已經在HTML解析期間並行下載。...

鼠標事件

在 JavaScript 中了解與鼠標事件的基本互動方式 在處理鼠標事件時,我們有以下能力: mousedown 鼠標按下 mouseup 鼠標釋放 click 點擊事件 dblclick 雙擊事件 mousemove 鼠標移動到元素上方時 mouseover 鼠標移動到元素或其子元素上方時 mouseenter 鼠標移動到元素上時。類似 mouseover 但不會冒泡(稍後會詳細解釋!) mouseout 鼠標移出元素或進入子元素時 mouseleave 鼠標移出元素時。類似 mouseout 但不會冒泡(稍後會詳細解釋!) contextmenu 右鍵點擊時打開上下文菜單 事件有重疊。在追踪 click 事件時,就如同追踪 mousedown 後跟著 mouseup 事件。在 dblclick 的情況下,click 也會被觸發兩次。 mousedown、mousemove 和 mouseup 可以組合使用以追踪拖放事件。 對於 mousemove,要小心,因為它在鼠標移動期間會觸發多次。我們需要進行節流處理,這是我們稍後在分析滾動時會談到的。 在事件處理程序中,我們可以訪問許多屬性。 例如,在鼠標事件中,可以通過檢查事件對象的 button 屬性來查看按下了哪個鼠標按鈕: const link = document.getElementById('my-link') link.addEventListener('mousedown', event => { // 鼠標按下 console.log(event.button) // 0=左鍵,2=右鍵 }) 以下是我們可以使用的所有屬性: altKey 如果事件觸發時按下了 Alt 鍵則為 true button 如果有,是觸發鼠標事件時按下的鍵的編號(通常 0 = 主按鈕,1 = 中間按鈕,2 = 右鍵)。適用於由點擊按鈕引起的事件(例如點擊事件) buttons 如果有,表示在任何鼠標事件上按下的按鈕的編號 clientX / clientY 鼠標指針相對於瀏覽器窗口的 x 和 y 坐標,不受滾動影響 ctrlKey 如果事件觸發時按下了 Ctrl 鍵則為 true metaKey 如果事件觸發時按下了 Meta 鍵則為 true movementX / movementY 鼠標指針相對於上次 mousemove 事件的位置的 x 和 y 坐標。用於跟踪移動時的鼠標速度 region 在 Canvas API 中使用 relatedTarget 事件的次要目標,例如在移動時 screenX / screenY 鼠標指針在屏幕坐標中的 x 和 y 坐標 shiftKey 如果事件觸發時按下了 Shift 鍵則為 true