JavaScript === ###### tags: `JavaScript` ###### tags: `JavaScript`, `frontend`, `backend` :::success :bulb: [**[github] javascript-study**](https://github.com/tsungjung411/javascript-study) ::: <br> [TOC] <br> ## Tutorial ### W3school - [JavaScript](https://www.w3schools.com/js) - [JavaScript Reference](https://www.w3schools.com/jsref) <br> ## 運算子 ### Nullish coalescing Operator 空值合併運算子 ?? > 關鍵字:JavaScript, JS, TypeScript, TS, operator, double question mark, ??, Nullish coalescing Operator, 空值合併運算子 > doc: > - [使用空值合併運算子](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/Optional_chaining#使用空值合併運算子) > - [Nullish coalescing operator (??)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator) ```javascript > x=100 < 100 > y=undefined < undefined > z=null < null > x ?? 123 < 100 > y ?? 123 < 123 > z ?? 123 < 123 ``` - 簡單講:如果不是空值,就直接拿來用,否則使用 default ``` f = (x, def) => x ? x : def; f(x, 123); f(y, 123); f(z, 123); ``` <br> <hr> <br> ## async & await, Promise ### MDN Web Docs (mozilla) - [async function](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Statements/async_function) ### test1: resolved ```javascript== new Promise((x, y)=>{ console.log('x:', x); console.log('y:', y); x(); }).then(()=> { console.log('succeeded'); }).catch(() => { console.log('failed'); }) ``` ![](https://i.imgur.com/2d9TIiW.png) ### test2: rejected ```javascript== new Promise((x, y)=>{ console.log('x:', x); console.log('y:', y); y(); }).then(()=> { console.log('succeeded'); }).catch(() => { console.log('failed'); }) ``` ![](https://i.imgur.com/zBoFoxn.png) ### 待消化 - [[Javascript]非同步的救星Promise](http://mis101bird.js.org/promise/) - [[JavaScript] 一次搞懂同步與非同步的一切:待會叫你 — 回呼函式(Callback Function)]([0](https://medium.com/itsems-frontend/javascript-callback-function-993abc2c0b42)) <br> <hr> <br> ## 字串 ### 格式化 - ### 使用 `${xxx}` 測試: ```javascript= var name = 'John' `Hello, ${name}` ``` 執行結果: ``` Hello, John ``` - ### 實作 prototype ```javascript= String.prototype.format = function() { var args = arguments; console.log('args:', args); console.log('string:', this); return this.replace(/{(\d+)}/g, function(match, number) { console.log('matcher:', match, number); return args[number]??match; }); }; ``` 測試: `'[[x={0} y={1} ?={3} z={2} ?={10} y={1} x={0} ]]'.format('x' ,'y', 'z')` 執行結果: ![](https://i.imgur.com/qMHDcDe.png) - ### [JavaScript: 如何使用 format 格式化字符串](https://www.letianbiji.com/web-front-end/js-string-format.html) 定義 prototype: ```javascript== String.prototype.format = function() { var args = arguments; var formated = this; for (var idx in args) { //console.log(idx, args[idx]); formated = formated.replaceAll('{' + idx + '}', args[idx]); } return formated; } ``` 測試: ``` '{1} {0} {0} {1}'.format('x', 'y') ``` 執行結果: ``` 'y x x y' ``` ### 子字串 - ### [js字串擷取函式slice、substring和substr的比較](https://codertw.com/%E5%89%8D%E7%AB%AF%E9%96%8B%E7%99%BC/266378/) - `slice(start,[end])` 行為同 java.substring, 以及可允許 負索引 - `substring(start,[end])` 行為同 java.substring, 但負索引皆被修正為 0 - `substr(start,[length])` 可允許 負索引 <br> <hr> <br> ## RegExp ### W3school - [JavaScript RegExp g Modifier](https://www.w3schools.com/jsref/jsref_regexp_g.asp) - `g`: A global match finds all matches (compared to only the first). <br> <hr> <br> ## DOM (Document Object Model) ### img ```typescript= const img = document.createElement('img'); img.src = 'https://edge.aif.tw/content/images/2020/10/EDGE2.png'; img.setAttribute('width', '100%'); img.setAttribute('style','margin: 1em;'); console.log(img); ``` ![](https://i.imgur.com/ZKUzWki.png) - [[MDN Web Docs] HTMLImageElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement) <br> ### ul+li ```typescript= const ul = document.createElement('ul'); let li; li = document.createElement('li'); li.innerHTML = 'abc'; ul.appendChild(li); li = document.createElement('li'); li.appendChild(document.createTextNode('xyz')) ul.appendChild(li); console.log(ul); ``` ![](https://i.imgur.com/YNESeX6.png) - [[MDN Web Docs] HTMLUListElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLUListElement) - [[MDN Web Docs] HTMLLIElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLIElement) <br> <hr> <br> ## JavaScript 特殊性質 ### Curry - ### [第 4 章:Curry(柯里化)](https://jigsawye.gitbooks.io/mostly-adequate-guide/content/ch4.html) ### call / apply / bind - ### [JavaScript - call,apply,bind](https://ithelp.ithome.com.tw/articles/10195896) - call 和 apply 差別 - call: 一個一個代入參數 - apply: 使用 array 代入 ### closure - ### [JavaScript - Closure (1)](https://ithelp.ithome.com.tw/articles/10195343) <br> <hr> <br> ## Operations ### iterate object > iterating key/value pairs - [How to Iterate through an object keys and values in JavaScript](https://attacomsian.com/blog/javascript-iterate-objects) ### remove all children - [Remove all child elements of a DOM node in JavaScript](https://stackoverflow.com/questions/3955229) ### is integer - [Check if character is number?](https://stackoverflow.com/questions/8935632) ### [Array](https://www.w3schools.com/jsref/jsref_obj_array.asp) - ### [JavaScript Array.from()](https://www.w3schools.com/jsref/jsref_from.asp) - Case1 ```javascript= Array.from("ABCDEFG") ``` 執行結果: ``` (7) ['A', 'B', 'C', 'D', 'E', 'F', 'G'] ``` - Case2: [從 arguments 型別轉成 array](https://ithelp.ithome.com.tw/articles/10195896) ```javascript= call1 = () => console.log(arguments) call1() // Uncaught ReferenceError: arguments is not defined call2 = function() { console.log(arguments); console.log('arguments.reduce:', arguments.reduce); console.log('array.reduce:', Array.from(arguments).reduce); } call2(1,2,3) ``` 執行結果: ``` Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ] arguments.reduce: undefined array.reduce: ƒ reduce() { [native code] } ``` - ### [JavaScript Array includes()](https://www.w3schools.com/jsref/jsref_includes_array.asp) - includes 類似於 `indexOf(searchElement, fromIndex)` - ### [JavaScript Array reduce()](https://www.w3schools.com/jsref/jsref_reduce.asp) - 就是彙整所有資訊,類似於 aggregate 概念 ```javascript= x = [1, 2, 3, 4] x.reduce((total, num) => { console.log(`total=${total} + num=${num}`); return total + num; }, 100) ``` ``` total=100 + num=1 total=101 + num=2 total=103 + num=3 total=106 + num=4 110 ``` ### encode / decode, escape / unescape - [try](https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_encodeuri) ![](https://i.imgur.com/Xox2yQf.png) ```html= <!DOCTYPE html> <html> <body> <h1>JavaScript Global Methods</h1> <h2>The encodeURI() Method</h2> <p id="demo1"></p> <p id="demo2"></p> <p id="demo3"></p> <p id="demo4"></p> <p id="demo5"></p> <p id="demo6"></p> <script> let uri = "my test.asp?name=ståle&car=saab"; let encoded = encodeURI(uri); document.getElementById("demo1").innerHTML = encodeURI(uri); document.getElementById("demo2").innerHTML = encodeURIComponent(uri); document.getElementById("demo3").innerHTML = escape(uri); document.getElementById("demo4").innerHTML = decodeURI(encodeURI(uri)); document.getElementById("demo5").innerHTML = decodeURIComponent(encodeURIComponent(uri)); document.getElementById("demo6").innerHTML = unescape(escape(uri)); </script> </body> </html> ``` - [`escape()`](https://www.w3schools.com/jsref/jsref_escape.asp) :warning: deprecated Use [encodeURI()](https://www.w3schools.com/jsref/jsref_encodeuri.asp) or [encodeURIComponent()](https://www.w3schools.com/jsref/jsref_encodeuricomponent.asp) instead. ### fetch - [[MDN] Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) - status: the status code - statusText: the status message <br> ### throw new Error - ### Question 在 js 中,想要 throw new Error() 但要攜帶 msg='Network response was not ok!', status_code=response.status 在 catch 之後要取出 msg & status_code - ### ChatGPT4 在 JavaScript 中,`Error` 物件通常只帶有一個 `message` 屬性。 如果你想要附加額外的數據,例如一個狀態碼,你可以擴展 `Error` 對象,或者在拋出錯誤時直接附加額外的屬性。 以下是兩種方法: - ### 方法 1: 擴展 `Error` 對象 你可以建立一個自訂的錯誤類,包含 message 和 statusCode: ```javascript= class NetworkError extends Error { constructor(message, statusCode) { super(message); this.statusCode = statusCode; } } // 使用自訂的錯誤類 fetch(`${apiUrl}/list_model`) .then(response => { if (!response.ok) { throw new NetworkError('Network response was not ok!', response.status); } return response.json(); }) .catch(error => { console.log(error.message); // "Network response was not ok!" console.log(error.statusCode); // 狀態碼,例如 404 或 500 }); ``` - ### 方法 2: 在拋出時附加屬性 如果你不想創建一個新的類,你也可以簡單地為 Error 物件添加屬性: ```javascript= fetch(`${apiUrl}/list_model`) .then(response => { if (!response.ok) { const error = new Error('Network response was not ok!'); error.statusCode = response.status; throw error; } return response.json(); }) .catch(error => { console.log(error.message); // "Network response was not ok!" console.log(error.statusCode); // 狀態碼,例如 404 或 500 }); ``` <br> ### store data - [How to store data in the DOM ?](https://www.geeksforgeeks.org/how-to-store-data-in-the-dom/) > 關鍵字:html dom store data <br> <hr> <br> ## fecth ### POST with json data ```javascript const url = "https://www.prisma-gene.com.tw/User/UsageLimits"; const data = { ApiUserId: "your_api_user_id", ApiUserKey: "your_user_key", Name: "your_name" }; fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error(error)); ``` <br> ### stream ```javascript= const url = 'http://10.78.26.241:83/api/models/generate'; const data = { model: 'llama2-7b-chat-0821-ft', inputs: 'Hello~', parameters: {'max_new_tokens': 100}, stream: true, }; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data), }) .then(response => { // 檢查 HTTP 狀態碼 if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } // 開始以流的方式處理數據 const reader = response.body.getReader(); // 定義 TextDecoder const textDecoder = new TextDecoder(); // 開始讀取數據 return reader.read().then(function processResult(result) { // 檢查是否已讀取完畢 if (result.done) { console.log('Stream ended'); return; } // 將二進制數據轉換為字符串 var chunk = textDecoder.decode(result.value); chunk = chunk.substr(6); chunk = JSON.parse(chunk) console.log('Received chunk:', chunk["generated_text"]); // 繼續讀取下一個數據块 return reader.read().then(processResult); }); }) .catch(error => console.error('Error:', error)); ``` <br> <hr> <br> ## script ### 範例1:打 request ```javascript= console.log('Hello, World!'); const url = 'http://10.78.26.241:30080/completion'; const data = { n_predict: 20, prompt: 'How are you?' }; const headers = { 'Content-Type': 'application/json' }; fetch(url, { method: 'POST', headers: headers, body: JSON.stringify(data) }).then(res => { console.log('status_code: ' + res.status); return res.json(); }).then(data => { console.log('data: ', data); }).catch(err => { console.log('err:', err); }); console.log('DONE!') ``` - 建立環境 ``` $ conda create -n nodejs python=3.10 nodejs -y $ node -v v18.18.2 ``` - 執行方式 ``` $ node script.js ``` - 執行結果: ```json Hello, World! DONE! status_code: 200 data: { content: " How has your week been? I'm feeling pretty good today, but a bit tired. It'", generation_settings: { frequency_penalty: 0, grammar: '', ignore_eos: false, logit_bias: [], min_p: 0.05000000074505806, mirostat: 0, mirostat_eta: 0.10000000149011612, mirostat_tau: 5, model: '/home/***/LLM_Models/TheBloke/Llama-2-7b-Chat-GGUF/llama-2-7b-chat.Q4_K_M.gguf', n_ctx: 2048, n_keep: 0, n_predict: 20, n_probs: 0, penalize_nl: true, presence_penalty: 0, repeat_last_n: 64, repeat_penalty: 1.100000023841858, seed: 4294967295, stop: [], stream: false, temp: 0.800000011920929, tfs_z: 1, top_k: 40, top_p: 0.949999988079071, typical_p: 1 }, model: '/home/***/LLM_Models/TheBloke/Llama-2-7b-Chat-GGUF/llama-2-7b-chat.Q4_K_M.gguf', prompt: 'How are you?', slot_id: 2, stop: true, stopped_eos: false, stopped_limit: true, stopped_word: false, stopping_word: '', timings: { predicted_ms: 622.838, predicted_n: 20, predicted_per_second: 32.111078643242706, predicted_per_token_ms: 31.1419, prompt_ms: 200.311, prompt_n: 5, prompt_per_second: 24.961185356770223, prompt_per_token_ms: 40.062200000000004 }, tokens_cached: 25, tokens_evaluated: 5, tokens_predicted: 20, truncated: false } ``` ![](https://hackmd.io/_uploads/r1rRqZgvT.png) <br> ### Q&A - ### run script.js - Question `script.js` 這種檔案要如何在 ubuntu 執行? - ChatGPT 要在 Ubuntu 上執行 JavaScript 檔案(例如 `script.js`),你需要安裝 Node.js。Node.js 是基於 Chrome V8 引擎的 JavaScript 執行時,它使你能夠在伺服器端執行 JavaScript。 以下是在 Ubuntu 上安裝 Node.js 並執行 JavaScript 檔案的步驟: ### 步驟 1:安裝 Node.js 打開終端機,執行以下命令安裝 Node.js: ```bash sudo apt-get update sudo apt-get install nodejs ``` 這將安裝 Node.js 執行時。 ### 步驟 2:安裝 npm(Node.js 套件管理器) ```bash sudo apt-get install npm ``` ### 步驟 3:建立並編輯 JavaScript 檔案 使用你喜歡的文字編輯器建立一個 JavaScript 檔案,例如 script.js。你可以使用命令列編輯器 nano: ```bash nano script.js ``` 在編輯器中,輸入你的 JavaScript 代碼,然後保存並退出。 ### 步驟 4:執行 JavaScript 檔案 在終端機中,使用以下命令執行你的 JavaScript 檔案: ```bash node script.js ``` 這將執行 `script.js` 中的 JavaScript 代碼,並在終端機中顯示輸出。 請確保你的 JavaScript 代碼不依賴於瀏覽器環境,因為 Node.js 是在伺服器端執行 JavaScript,並沒有 DOM(文件物件模型)等瀏覽器相關的功能。如果你需要在瀏覽器中執行 JavaScript,你可以使用瀏覽器的開發者工具或將代碼嵌入到 HTML 頁面中。