1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | 很好的問題!讓我詳細解釋 JavaScript 的這些基礎語法: ## 1. `let` vs 其他變數宣告方式 ### 三種變數宣告方式對比 #### `var`(舊式,ES5) ```javascript var name = "John"; var age = 25; // 特性: // 1. 函數作用域 // 2. 可以重複宣告 // 3. 會提升 (hoisting) ``` #### `let`(現代,ES6/2015) ```javascript let isLocked = true; let isAlwaysOpen = false; // 特性: // 1. 區塊作用域 (block scope) // 2. 不可重複宣告 // 3. 不會提升到可用狀態 ``` #### `const`(常數,ES6/2015) ```javascript const MQTT_BROKER = "broker.emqx.io"; const MAX_RETRY = 3; // 特性: // 1. 區塊作用域 // 2. 不可重新賦值 // 3. 必須立即初始化 ``` ### 實際差異範例 #### 作用域差異 ```javascript function example() { if (true) { var varVariable = "我是 var"; let letVariable = "我是 let"; } console.log(varVariable); // 正常:我是 var console.log(letVariable); // 錯誤:ReferenceError } ``` #### 重複宣告 ```javascript var name = "John"; var name = "Jane"; // 正常,會覆蓋 let age = 25; let age = 30; // 錯誤:SyntaxError(重複宣告) let age = 25; age = 30; // 正常,重新賦值 ``` #### 為什麼現代程式碼偏好 `let`? ```javascript // 避免意外的作用域問題 for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100); // 輸出:3, 3, 3 } for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100); // 輸出:0, 1, 2 } ``` ## 2. `.end()` 方法的作用 ### `.end()` 不是刪除變數! ```javascript if (mqttClient) { mqttClient.end(); // 關閉 MQTT 連線 } ``` **實際作用:** - 優雅地關閉 MQTT 連線 - 發送 DISCONNECT 封包給 broker - 清理網路資源 - **變數 `mqttClient` 依然存在**,只是連線已關閉 ### 完整的連線管理流程 ```javascript function connectMQTT() { // 如果已經連線,先斷開舊連線 if (isConnected) { if (mqttClient) { mqttClient.end(); // 關閉連線,但不刪除變數 } return; } // 建立新連線 mqttClient = mqtt.connect(brokerUrl, options); // 重新賦值 } ``` ### 變數 vs 物件的生命週期 ```javascript let mqttClient = null; // 1. 宣告變數 mqttClient = mqtt.connect(...); // 2. 變數指向 MQTT 物件 // 物件被建立,連線開始 mqttClient.end(); // 3. 呼叫物件方法關閉連線 // 物件還在,但連線已斷 mqttClient = null; // 4. 變數設為 null // 物件會被垃圾回收機制清理 ``` ## 3. 實際的物件生命週期管理 ### 正確的清理方式 ```javascript function disconnectMQTT() { if (mqttClient) { // 1. 關閉連線 mqttClient.end(); // 2. 清理變數參考 mqttClient = null; // 3. 更新狀態 isConnected = false; updateMQTTStatus(false); } } ``` ### 為什麼要分兩步? ```javascript // 只做 .end() 的情況: mqttClient.end(); // mqttClient 還是指向物件,但連線已關閉 // 如果後續程式碼嘗試使用,可能會有未預期的行為 // 完整清理: mqttClient.end(); mqttClient = null; // 變數明確設為 null,避免誤用 ``` ## 4. 實務中的變數管理模式 ### 模組級別的狀態管理 ```javascript // 全域狀態變數(用 let) let isLocked = true; // 可變狀態 let mqttClient = null; // 連線物件參考 let progressInterval = null; // 計時器參考 // 設定常數(用 const) const LOCK_TIMEOUT = 5000; const MQTT_OPTIONS = { keepalive: 60, clean: true }; ``` ### 函數內的臨時變數 ```javascript function sendLockCommand() { const timestamp = Date.now(); // 常數 let retryCount = 0; // 可變計數器 const maxRetries = 3; // 常數 // 使用這些變數... } ``` ## 5. 常見的 JavaScript 物件管理模式 ### 清理資源的完整範例 ```javascript class MQTTManager { constructor() { this.client = null; this.isConnected = false; this.reconnectTimer = null; } connect() { // 清理舊連線 this.disconnect(); // 建立新連線 this.client = mqtt.connect(url, options); this.setupEventHandlers(); } disconnect() { // 清理計時器 if (this.reconnectTimer) { clearInterval(this.reconnectTimer); this.reconnectTimer = null; } // 關閉 MQTT 連線 if (this.client) { this.client.end(); this.client = null; } // 更新狀態 this.isConnected = false; } } ``` ## 總結 - **`let`:** 現代的區塊作用域變數宣告,比 `var` 更安全 - **`.end()`:** 是物件的方法,用來關閉連線,不是刪除變數 - **變數管理:** 需要區分變數參考和物件生命週期 - **最佳實務:** 使用 `let`/`const` 取代 `var`,適當清理資源參考 你的程式碼使用 `let` 是正確的現代 JavaScript 寫法! |
Direct link: https://paste.plurk.com/show/aAva3UtJQ1OGVpvRVDJ6