裸辭8年前端的面試筆記——JavaScript篇(一)

裸辭后的第二個月開始準備找工作,今天是第三天目前還沒有面試,現在的行情是一言難盡,都在瘋狂的壓價。

下邊是今天復習的個人筆記

一、事件循環

JavaScript 的事件循環(Event Loop)是其實現異步編程的關鍵機制。

從原理上講,JavaScript 是單線程語言,只有一個主線程來執行代碼,這意味著同一時間只能做一件事。但為了實現異步操作(比如處理用戶交互、網絡請求等),引入了事件循環機制。
事件循環涉及到幾個重要概念:

  1. 調用棧(Call Stack): 是一種數據結構,用于記錄函數的調用關系。函數調用時入棧,執行完畢后出棧。
  2. 任務隊列(Task Queue): 也叫消息隊列,用于存放異步操作的回調函數。當異步操作完成時,對應的回調函數會被放入任務隊列。
  3. 宏任務(Macrotask): 包括 script (整體代碼)、setTimeout、setInterval、setImmediate(Node.js 環境)、requestAnimationFrame 等。
  4. 微任務(Microtask): 包括 Promise 的 then、catch、finally,MutationObserver 等。

事件循環的執行過程大致如下:

  1. 首先執行調用棧中的同步任務。
  2. 當遇到異步任務時,異步任務會被掛起,不會阻塞主線程,繼續執行同步任務。
  3. 當同步任務執行完畢后,開始處理微任務隊列,依次執行微任務隊列中的任務。
  4. 微任務執行完畢后,開始執行宏任務隊列中的任務,每執行一個宏任務,就會檢查并執行微任務隊列。
  5. 重復上述過程,不斷循環,這就是事件循環。

例如:

console.log('start');setTimeout(() => {console.log('setTimeout');
}, 0);Promise.resolve().then(() => {console.log('Promise then');
});console.log('end');

在這段代碼中,首先 console.log('start') console.log('end') 作為同步任務在調用棧中依次執行。setTimeout 是宏任務,會被放到宏任務隊列。Promise.resolve().then() 是微任務,會被放到微任務隊列。當同步任務執行完后,開始執行微任務隊列中的 Promisethen 回調,打印 Promise then,最后執行宏任務隊列中的 setTimeout 回調,打印 setTimeout

二、Promise.all 和 Promise.race

Promise.all 和 Promise.race ,它們都是 Promise 的靜態方法,在處理多個 Promise 時非常有用,以下是它們的詳細介紹:

Promise.all

  • 它接受一個包含多個 Promise 對象的可迭代對象(比如數組)作為參數。
  • 只有當傳入的所有 Promise 都成功時,Promise.all 才會返回一個成功的 Promise,其結果是一個包含所有 Promise 結果的數組,順序和傳入的 Promise 順序一致。
  • 只要有一個 Promise 失敗,Promise.all 就會立即返回一個失敗的 Promise,失敗原因就是第一個失敗的 Promise 的原因。

例如:

const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);Promise.all([promise1, promise2, promise3]).then((values) => {console.log(values); //輸出: [1, 2, 3]}).catch((error) => {console.error(error);});

有失敗的Promise:

const promise1 = Promise.resolve(1);
const promise2 = Promise.reject(new Error('Promise 2 failed'));
const promise3 = Promise.resolve(3);Promise.all([promise1, promise2, promise3]).then((values) => {console.log(values); // 不會輸出}).catch((error) => {console.error(error.message); // 輸出: Promise 2 failed});

Promise.race

  • 同樣接受一個包含多個 Promise 對象的可迭代對象作為參數。
  • 只要其中一個 Promise 率先改變狀態(無論是成功還是失敗),Promise.race 就會返回這個 Promise 的結果或原因。

例如:

const promise1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('Promise 1 resolved');}, 2000);
});const promise2 = new Promise((resolve, reject) => {setTimeout(() => {reject(new Error('Promise 2 failed'));}, 1000);
});Promise.race([promise1, promise2]).then((value) => {console.log(value);}).catch((error) => {console.error(error.message); // Promise 2 failed});

簡單來說,Promise.all 強調所有 Promise 都成功,Promise.race 則關注誰先改變狀態。

純JS實現Promise,并集成all和race

下面是一個簡單實現 Promise 并添加 all 和 race 方法的代碼示例,解釋了其基本原理和實現思路:

// 自定義Promise類
function MyPromise(executor) {this.status = 'pending';this.value = null;this.reason = null;this.onResolvedCallbacks = [];this.onRejectedCallbacks = [];const resolve = (val) => {if (this.status === 'pending') {this.status = 'fulfilled';this.value = val;this.onResolvedCallbacks.forEach(callback => callback(this.value));}};const reject = (err) => {if (this.status === 'pending') {this.status ='rejected';this.reason = err;this.onRejectedCallbacks.forEach(callback => callback(this.reason));}};try {executor(resolve, reject);} catch (error) {reject(error);}
}// Promise.prototype.then方法實現
MyPromise.prototype.then = function (onFulfilled, onRejected) {onFulfilled = typeof onFulfilled === 'function'? onFulfilled : value => value;onRejected = typeof onRejected === 'function'? onRejected : reason => { throw reason };let nextPromise;if (this.status === 'fulfilled') {nextPromise = new MyPromise((resolve, reject) => {try {const x = onFulfilled(this.value);resolvePromise(nextPromise, x, resolve, reject);} catch (error) {reject(error);}});}if (this.status ==='rejected') {nextPromise = new MyPromise((resolve, reject) => {try {const x = onRejected(this.reason);resolvePromise(nextPromise, x, resolve, reject);} catch (error) {reject(error);}});}if (this.status === 'pending') {nextPromise = new MyPromise((resolve, reject) => {this.onResolvedCallbacks.push((value) => {try {const x = onFulfilled(value);resolvePromise(nextPromise, x, resolve, reject);} catch (error) {reject(error);}});this.onRejectedCallbacks.push((reason) => {try {const x = onRejected(reason);resolvePromise(nextPromise, x, resolve, reject);} catch (error) {reject(error);}});});}return nextPromise;
};// 輔助函數,處理then方法中返回值的邏輯
function resolvePromise(promise2, x, resolve, reject) {if (promise2 === x) {return reject(new TypeError('Chaining cycle detected for promise'));}if (x instanceof MyPromise) {x.then(resolve, reject);} else if (typeof x === 'object' || typeof x === 'function') {if (x === null) {return resolve(x);}let called = false;try {const then = x.then;if (typeof then === 'function') {then.call(x,(y) => {if (called) return;called = true;resolvePromise(promise2, y, resolve, reject);},(r) => {if (called) return;called = true;reject(r);});} else {resolve(x);}} catch (error) {if (called) return;called = true;reject(error);}} else {resolve(x);}
}// 實現Promise.all方法
MyPromise.all = function (promises) {return new MyPromise((resolve, reject) => {const result = [];let count = 0;if (promises.length === 0) {resolve(result);} else {promises.forEach((p, index) => {MyPromise.resolve(p).then((value) => {result[index] = value;count++;if (count === promises.length) {resolve(result);}}).catch((error) => {reject(error);});});}});
};// 實現Promise.race方法
MyPromise.race = function (promises) {return new MyPromise((resolve, reject) => {promises.forEach((p) => {MyPromise.resolve(p).then((value) => {resolve(value);}).catch((error) => {reject(error);});});});
};

使用自定義的 MyPromise

// 使用示例
const promise1 = new MyPromise((resolve) => {setTimeout(() => {resolve(1);}, 1000);
});const promise2 = new MyPromise((resolve, reject) => {setTimeout(() => {reject(new Error('Promise 2 failed'));}, 500);
});// 使用then方法
promise1.then((value) => {console.log(value);}).catch((error) => {console.error(error);});// 使用all方法
MyPromise.all([promise1, promise2]).then((values) => {console.log(values);}).catch((error) => {console.error(error);});// 使用race方法
MyPromise.race([promise1, promise2]).then((value) => {console.log(value);}).catch((error) => {console.error(error);});

在上述代碼中,首先定義了一個 MyPromise 類,實現了基本的 Promise 功能,包括 then 方法。然后添加了 all 和 race 靜態方法,分別用于按順序處理多個 Promise(all)和誰先有結果就返回誰(race)。resolvePromise 函數則處理了 then 方法中返回值的復雜邏輯,確保遵循 Promise/A+ 規范。

三、閉包

閉包是面試中常見的一個考點,復習也是很有必要的,在工作中使用閉包的場景很多比如在Vue和React組件就是個大閉包,還有防抖節流等函數的封裝等等。

1. 什么是閉包?

閉包是指函數和與其相關的詞法環境的組合。當一個內部函數在其外部函數返回后仍然能訪問外部函數的變量時,就創建了閉包。

function outer() {let count = 0;function inner() {count++;console.log(count);}return inner;
}const closureFn = outer();
closureFn(); // 1
closureFn(); // 2

在這個例子中,inner函數形成了閉包,即使 outer 函數已經執行完畢,inner 函數依然可以訪問 outer 函數作用域內的 count 變量。

2. 閉包有什么作用?

  • 數據私有性: 可以隱藏變量,通過閉包,外部代碼無法直接訪問函數內部的變量,只能通過閉包返回的函數來操作這些變量,實現數據的封裝。
  • 狀態保存: 閉包能記住創建時的狀態,比如在計數器的例子中,每次調用閉包函數,都能記住上次 count 的值并進行操作。
  • 柯里化: 閉包是實現函數柯里化的基礎,柯里化可以將多參數函數轉化為一系列單參數函數,提高函數的復用性和靈活性。柯里化后邊會延伸描述

3. 閉包可能會帶來什么問題?

  • 內存泄漏: 如果閉包函數一直存在,并且引用了一些大的對象或不再需要的變量,這些變量不會被垃圾回收機制回收,可能會導致內存占用過高,出現內存泄漏。例如:
    function createBigObject() {const bigArray = new Array(1000000).fill(0);return function () {// 閉包函數一直存在,bigArray無法被回收console.log('closure');};
    }const leakyClosure = createBigObject();
    
  • 變量的值不是預期的: 在循環中使用閉包時,如果不注意,可能會得到意外的結果。比如:
    const functions = [];
    for (var i = 0; i < 5; i++) {functions.push(() => {console.log(i);});
    }
    functions.forEach(fn => fn()); 
    // 輸出 5 5 5 5 5,因為這里的i是最后循環結束時的值
    
    可以通過立即執行函數或使用 let 關鍵字來解決這個問題。如下:
    const functions = [];
    for (let i = 0; i < 5; i++) {functions.push(() => {console.log(i);});
    }
    functions.forEach(fn => fn()); 
    // 輸出 0 1 2 3 4
    

4. 如何避免閉包導致的內存泄漏?

當閉包不再使用時,手動將閉包函數賦值為 null,這樣相關的變量就可以被垃圾回收機制回收。例如:

function createClosure() {let data = { a: 1 };return function () {console.log(data.a);};
}let closureFn = createClosure();
// 使用閉包函數
closureFn();
// 不再使用閉包時,將其賦值為null
closureFn = null;

5. 實際開發中,不專門手動將閉包引用的變量置為null

實際開發中,閉包導致的內存泄漏本質是 “外部引用未正確釋放”,而非閉包語法本身的問題。現代 GC 機制和框架已能處理大部分場景,手動置空閉包變量既不現實也無必要。開發者的核心任務是:

  • 正確管理外部依賴(移除事件監聽、清除定時器、避免不合理的全局引用);
  • 依賴框架的生命周期鉤子處理副作用,讓閉包隨上下文自然釋放。

只有在極端或不規范的場景下,才需針對性地手動清理,但這也應優先通過切斷外部引用來實現,而非直接操作閉包內部的變量。

四、柯里化

**柯里化(Currying)**是一種在函數式編程中廣泛使用的技術,它允許你將一個多參數函數轉換為一系列單參數函數。以下從定義、原理、用途、示例等方面詳細介紹柯里化。

定義與原理

  • 定義: 柯里化是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,并且返回接受余下的參數而且返回結果的新函數的技術。簡單來說,就是將一個多參數函數拆分成多個單參數函數。
  • 原理: 利用閉包的特性,讓函數記住之前傳入的參數,當參數數量達到原函數所需的參數數量時,執行原函數邏輯。

用途

參數復用: 當多次調用同一個函數,并且傳遞的參數大部分相同時,使用柯里化可以復用這些相同的參數。
延遲計算: 可以在需要的時候再傳入剩余的參數進行計算,而不是一次性傳入所有參數。
動態創建函數: 根據不同的參數動態生成不同的函數。

示例

以下是一個簡單的 JavaScript 示例,展示如何實現柯里化:

// 定義一個普通的加法函數
function add(a, b) {return a + b;
}// 實現柯里化函數
function curry(func) {return function curried(...args) {if (args.length >= func.length) {return func.apply(this, args);} else {return function (...nextArgs) {return curried.apply(this, args.concat(nextArgs));};}};
}// 將 add 函數進行柯里化
const curriedAdd = curry(add);// 使用柯里化函數
const add5 = curriedAdd(5);
console.log(add5(3)); // 輸出 8    

代碼解釋

  • curry 函數: 接受一個函數 func 作為參數,返回一個新的函數 curried。
  • curried 函數: 接受任意數量的參數 args,如果 args 的長度大于或等于原函數 func 的參數長度,則直接調用 func 并返回結果;否則,返回一個新的函數,該函數會將之前的參數和新傳入的參數合并后再次調用 curried 函數。
  • curriedAdd 函數: 是 add 函數柯里化后的結果。通過 curriedAdd(5) 得到一個新的函數 add5,這個函數記住了之前傳入的參數 5,當調用 add5(3) 時,將 5 和 3 相加并返回結果。

實際應用場景

  • **日志記錄:**在日志記錄時,通常會有一些固定的參數(如日志級別、日志來源等),可以使用柯里化來復用這些參數。
    function log(level, source, message) {console.log(`[${level}] [${source}] ${message}`);
    }const curriedLog = curry(log);
    const errorLog = curriedLog('ERROR');
    const appErrorLog = errorLog('App');
    appErrorLog('Something went wrong!'); // 輸出 [ERROR] [App] Something went wrong!
    
  • 事件處理: 在處理事件時,可能需要傳遞一些額外的參數,可以使用柯里化來動態創建事件處理函數。
    <!DOCTYPE html>
    <html lang="en"><head><meta charset="UTF-8">
    </head><body><button id="myButton">Click me</button><script>function handleClick(message, event) {console.log(`${message}: ${event.type}`);}const curriedHandleClick = curry(handleClick);const clickWithMessage = curriedHandleClick('Button clicked');const button = document.getElementById('myButton');button.addEventListener('click', clickWithMessage);</script>
    </body></html>
    
    在這個示例中,通過柯里化創建了一個帶有固定消息的事件處理函數 clickWithMessage,當按鈕被點擊時,會輸出相應的日志信息。

不推薦使用柯里化的場景

  • 簡單一次性調用: 若函數僅調用一次,且參數無復用可能,直接調用普通函數更高效(如 sum(1, 2, 3) 無需柯里化)。
  • 參數順序依賴強或易混淆: 柯里化要求嚴格按參數順序傳參,若參數含義不明確(如log('ERROR', 'App', '消息')中 ‘App’ 可能是來源或消息),可能導致調用時參數錯位。
  • 追求極致性能的場景: 雖然現代引擎優化較好,但柯里化涉及閉包和多層函數嵌套,在極端高頻調用(如循環內)時可能存在微小性能損耗(需實測驗證)

總結

  • 用: 當需要參數復用、延遲計算、函數組合或動態生成定制函數,且代碼風格兼容函數式思維時。
  • 慎: 當參數邏輯復雜、可讀性可能受損,或團隊對 FP 不熟悉時,優先考慮更直觀的參數傳遞方式(如對象、默認參數)。

柯里化的核心價值在于將 “不變的部分” 與 “變化的部分” 分離,通過函數的 “預配置” 提高代碼的靈活性和復用性。實際開發中,可從小規模場景(如工具函數、配置類函數)開始嘗試,逐步判斷是否符合項目需求。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/82257.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/82257.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/82257.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

什么是死信隊列?死信隊列是如何導致的?

死信交換機&#xff08;Dead Letter Exchange&#xff0c;DLX&#xff09; 定義&#xff1a;死信交換機是一種特殊的交換機&#xff0c;專門用于**接收從其他隊列中因特定原因變成死信的消息**。它的本質還是交換機&#xff0c;遵循RabbitMQ中交換機的基本工作原理&#xff0c…

9. 從《蜀道難》學CSS基礎:三種選擇器的實戰解析

引言&#xff1a;當古詩遇上現代網頁設計 今天我們通過李白的經典詩作《蜀道難》來學習CSS的三種核心選擇器。這種古今結合的學習方式&#xff0c;既能感受中華詩詞的魅力&#xff0c;又能掌握實用的網頁設計技能。讓我們開始這場穿越時空的技術之旅吧&#xff01; 一、HTML骨架…

三角網格減面算法及其代表的算法庫都有哪些?

以下是三角網格減面算法及其代表庫/工具的詳細分類&#xff0c;涵蓋經典算法和現代實現&#xff1a; ??1. 頂點聚類&#xff08;Vertex Clustering&#xff09;?? ??原理??&#xff1a;將網格空間劃分為體素柵格&#xff0c;合并每個柵格內的頂點。??特點??&#…

URP - 屏幕圖像(_CameraOpaqueTexture)

首先需要在unity中開啟屏幕圖像開關才可以使用該紋理 同樣只有不透明對象才能被渲染到屏幕圖像中 若想要該對象不被渲染到屏幕圖像中&#xff0c;可以將其Shader的渲染隊列改為 "Queue" "Transparent" 如何在Shader中使用_CameraOpaqueTexture&#xf…

vue 和 html 的區別

使用 Vue.js 和原生 HTML 開發 Web 應用有顯著的區別&#xff0c;主要體現在開發模式、功能擴展、性能優化和維護性等方面。以下是兩者的對比分析&#xff1a; &#x1f9f1; 原生 HTML&#xff08;HTML CSS JavaScript&#xff09; 特點&#xff1a; 靜態結構&#xff1a;H…

LeetCode[226] 翻轉二叉樹

思路&#xff1a; 使用遞歸&#xff0c;歸根結底還是左右節點互相倒&#xff0c;那么肯定需要一個temp節點在中間傳遞&#xff0c;最后就是遞歸&#xff0c;沒什么說的 代碼&#xff1a; /*** Definition for a binary tree node.* public class TreeNode {* int …

冪等的幾種解決方案以及實踐

目錄 什么是冪等&#xff1f; 解決冪等的常見解決方案&#xff1a; 唯一標識符案例 數據庫唯一約束 案例 樂觀鎖案例 分布式鎖&#xff08;Distributed Locking&#xff09; 實踐精選方案 首先 為什么不直接使用分布式鎖呢&#xff1f; 自定義實現冪等組件&#xff01…

PowerShell中的Json處理

1.定義JSON字符串變量 PS C:\WINDOWS\system32> $body {"Method": "POST","Body": {"model": "deepseek-r1","messages": [{"content": "why is the sky blue?","role"…

奧威BI:AI+BI深度融合,重塑智能AI數據分析新標桿

在數字化浪潮席卷全球的今天&#xff0c;企業正面臨著前所未有的數據挑戰與機遇。如何高效、精準地挖掘數據價值&#xff0c;已成為推動業務增長、提升競爭力的核心議題。奧威BI&#xff0c;作為智能AI數據分析領域的領軍者&#xff0c;憑借其創新的AIBI融合模式&#xff0c;正…

【Linux網絡】網絡協議基礎

網絡基礎 計算機網絡背景 獨立模式:計算機之間相互獨立 網絡互聯:多臺計算機連接在一起,完成數據共享 局域網LAN:計算機數量更多了,通過交換機和路由器連接在一起 廣域網WAN:將遠隔千里的計算機都連在一起 所謂"局域網"和"廣域網"只是一個相對的概念.比…

LabVIEW表面粗糙度測量及算法解析

在制造業和科研領域&#xff0c;表面粗糙度測量對保障產品質量、推動材料研究意義重大。表面粗糙度作為衡量工件表面加工質量的關鍵指標&#xff0c;直接影響著工件諸如磨損、密封、疲勞等機械性能。隨著技術的發展&#xff0c;LabVIEW 在表面粗糙度測量及數據處理中發揮著不可…

深入探索 JavaScript 中的模塊對象

引言 在現代 JavaScript 開發中&#xff0c;模塊化編程是一項至關重要的技術。它允許開發者將代碼拆分成多個獨立的模塊&#xff0c;每個模塊專注于單一功能&#xff0c;從而提高代碼的可維護性、可測試性和復用性。而模塊對象則是模塊化編程中的核心概念之一&#xff0c;它為…

Linux——Mysql數據庫

目錄 一&#xff0c;數據庫簡介 二&#xff0c;數據庫的基本概念 1&#xff0c;數據 2&#xff0c;數據庫和數據庫表 3&#xff0c;數據庫管理系統和數據庫系統 三&#xff0c;主流數據庫介紹 四&#xff0c;數據庫的兩大類型 1&#xff0c;關系型數據庫 主鍵 外鍵 2…

73頁最佳實踐PPT《DeepSeek自學手冊-從理論模型訓練到實踐模型應用》

這份文檔是一份關于 DeepSeek 自學手冊的詳細指南&#xff0c;涵蓋了 DeepSeek V3 和 R1 模型的架構、訓練方法、性能表現以及使用技巧等內容。它介紹了 DeepSeek V3 作為強大的 MoE 語言模型在數學、代碼等任務上的出色表現以及其訓練過程中的創新架構如多頭潛在注意力和多 To…

LabVIEW 2019 與 NI VISA 20.0 安裝及報錯處理

在使用 Windows 11 操作系統的電腦上&#xff0c;同時安裝了 LabVIEW 2019 32 位和 64 位版本的軟件。此前安裝的 NI VISA 2024 Q1 版&#xff0c;該版本與 LabVIEW 2019 32 位和 64 位不兼容&#xff0c;之后重新安裝了 NI VISA 20.0。從說明書來看&#xff0c;NI VISA 20.0 …

基于Centos7的DHCP服務器搭建

一、準備實驗環境&#xff1a; 克隆兩臺虛擬機 一臺作服務器&#xff1a;DHCP Server 一臺作客戶端&#xff1a;DHCP Clinet 二、部署服務器 在網絡模式為NAT下使用yum下載DHCP 需要管理員用戶權限才能下載&#xff0c;下載好后關閉客戶端&#xff0c;改NAT模式為僅主機模式…

最全盤點,趕緊收藏:2025 年全網最全的 Java 技術棧內容梳理(持續更新中)

大家好&#xff0c;我是栗箏i&#xff0c;是一個擁有 5 年經驗的 Java 開發工程師和技術博主&#xff0c;曾有多年在國內某大廠工作的經歷。從 2022 年 10 月份開始&#xff0c;我將持續梳理出全面的 Java 技術棧內容&#xff0c;一方面是對自己學習內容進行整合梳理&#xff0…

【項目實踐】boost 搜索引擎

1. 項目展示 boost搜索引擎具體講解視頻 2. 項目背景 對于boost庫&#xff0c;官方是沒有提供搜索功能的&#xff0c;我們這個項目就是來為它添加一個站內搜索的功能。 3. 項目環境與技術棧 ? 項目環境&#xff1a; ubuntu22.04、vscode ? 技術棧&#xff1a; C/C、C11、S…

一個簡單的MCP測試與debug

最近MCP挺火&#xff0c;我也跟著網上教程試試&#xff0c;參考如下&#xff0c;感謝原博主分享&#xff1a; https://zhuanlan.zhihu.com/p/1891227835722606201https://zhuanlan.zhihu.com/p/1891227835722606201 MCP是啥&#xff1f;技術原理是什么&#xff1f;一個視頻搞…

深度學習系統學習系列【7】之卷積神經網絡(CNN)

文章目錄 說明卷積神經網絡概述(Convolutional Neural Network,CNN)卷積神經網絡的應用圖像分類與識別圖像著色自然語言處理NLP卷積神經網絡的結構卷積神經網絡中的數據流動 CNN與ANN的關系 卷積操作Padding 操作滑動窗口卷積操作網絡卷積層操作矩陣快速卷積Im2col算法GEMM算法…