Mitour
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    --- ###### tags: `JavaScript` `程式筆記` --- # JavaScript 筆記整理 <!-- > [time=Sun, Apr 4, 2021 10:00 PM] --> :::info > [time=Wed, Aug 3, 2022 9:21 AM] 內容搬移至 [notion](https://www.notion.so/JavaScript-6344f85cb1634f0a98e0bff286ef7167) ::: [深入淺出前端開發](https://f2e.kalan.dev/javascript-basic/2.html#ecmascript) * ECMAScript 是規格,JavaScript 是實作。同樣實作了 ECMAScript 的還有 ActionScript * ECMAScript 每年都會發布一次 * ECMAScript 成為正式規格需要經過五個階段 * 每位開發者都可以提出草案 ## 直譯式語言 [【JS課程筆記】-直譯式語言 vs 編譯式語言](https://medium.com/ivycodefive/js%E8%AA%B2%E7%A8%8B%E7%AD%86%E8%A8%98-%E7%9B%B4%E8%AD%AF%E5%BC%8F%E8%AA%9E%E8%A8%80-vs-%E7%B7%A8%E8%AD%AF%E5%BC%8F%E8%AA%9E%E8%A8%80-ab584edaa762) > 直譯器轉換過程 (以變數為例) > 1. 將語法基本單元化 : 變數還未被定義、賦予值,只是先將結構中的關鍵字一一取出來。 > 1. 轉為抽象結構樹 : 轉為像是JSON的資料格式,將整個結構樹定義出來,需特別注意,程式碼在此階段還未真正運行。 > 1. 代碼生成 : 會因執行環境不同 (例如使用瀏覽器,或使用Node.js),生成的代碼也會有點不同,在代碼生成之後才會真正運行。 ## `var` & `let` & `const` 推薦觀看直播:[直播共筆](https://www.notion.so/JS-var-let-const-6c4d85fc28fc42a9aa2b6c303b276748) {%youtube FGdKdn_CnWo %} ### 為什麼要宣告變數? 如果不宣告,都會變成全域變數。造成全域污染 ```javascript= // 沒有宣告變數 a = 0; function fn(){ a = 1; } console.log(a); // output: 1 ``` ```javascript= // 有宣告變數,這邊 a 的作用域就只在 fn() 內 function fn() { var a = 0; } console.log(a); // output: a is not defined ``` 如果不宣告,這個 a 會變成 window 的「屬性」,宣告了就是「變數」,屬性可以被刪除,變數不行 ```javascript= a = 0; delete window.a; console.log(window); // 可以看到 a:0 是屬性 console.log(a); // a is not defined let b = 0; delete window.b; console.log(b); // 0 ``` ### 作用域 ![作用域](https://i.imgur.com/tLZ3UPi.jpg) <!-- > photo by 六角學院課程 --> JaveScript 屬於靜態作用域,又稱為語法作用域。 變數的作用域在語法解析時,就已經確定作用域,且不會再改變。 ![靜態作用域](https://i.imgur.com/mRVZBAN.jpg) <!-- > photo by 六角學院課程 --> ### `var` 跟 `let` 差異 重複宣告 ```javascript= // var 可以重複宣告 var a = 0; var a = 1; console.log(a); // 1 // let 已經宣告就過不能再重複宣告 let a = 0; let a = 1; console.log(a); // Identifier 'a' has already been declared ``` block 作用域 ```javascript= // var 沒有 block 作用域,只有分全域(global) 跟 function(local) { var a = 1; } console.log(a); // 1 // let 有 block 作用域 { let b = 2; } console.log(b); // b is not defined ``` for 也算是一個 block ```javascript= for (var i = 0; i < 10; i++) { } console.log(i); // 10 for (let j = 0; j < 10; j++) { } console.log(j); // j is not defined ``` 上例延伸 ```javascript= for (var i = 0; i < 10; i++) { setTimeout(() => { console.log(i); // 10 次(0~9) 10 }, 0); } // 輸出 10 因為 setTimeout 屬於非同步行為 // JS 默認在所有事件結束後才會執行非同步行為 // 所以執行 setTimeout 時 i 已經跳出 for 了 for (let j = 0; j < 10; j++) { setTimeout(() => { console.log(j); // 0~9 }, 0); } // 這邊我們知道在 for 迴圈裡使用 var 時 setTimeout 都是輸出 10 // 但 let 卻可以正常輸出 0~9 // 原因就是 let 屬於 block 作用域 這讓每個 i 都獨立存在於 block 內 // 這也是為何 let 比 var 穩定很多的原因 // 另外這是一個常見考題 下次遇到就知道怎麼做囉~~(用 let 啦哪次不用) ``` [hoisting\*](#hoisting) 和 [暫時性死區(TDZ)\*](#let-跟-const-的-hoisting) ```javascript= console.log(a); // undefined var a = 1; console.log(a); // 1 console.log(b); // Cannot access 'a' before initialization let b = 1; ``` :::info 結論:用 `let` 取代 `var` ::: ### `const` 不可重新賦值 ```javascript= const a = 1; a = 3; // Assignment to constant variable. ``` 物件傳參考的特性 ```javascript= // 可以改變 a 的 value const a = { name: 'me', } a.name = 'etc' console.log(a); // {name: 'etc'} // 不能將 a 重新指向 const a = { name: 'me', } a = { name: 'etc', } // Assignment to constant variable. ``` :::info 結論:確定不會重新賦值的,能用 `const` 就不要用 `let` ::: ### 使用時機 `var`, `let`, `const` 都有其使用時機,如果不確定怎麼用,可以使用規範如:[ESLint](https://eslint.org/docs/user-guide/getting-started) 來協助,VSCode 有套件而且預設就有安裝,使用教學:[在 VSCode 啟用程式碼規範工具 (ESLint)](https://www.casper.tw/tool/2017/11/09/coding-style/) ![ESLint](https://i.imgur.com/SmTItIf.png) :::info 備註:ESLint 規範並**不鼓勵**使用 `var` ::: ## ES6,7,8,9,10,11中,用一次就上癮的語法 [共筆](https://paper.dropbox.com/doc/ES67891011--BjL8XWN7qwQxxMeFAdWJYgdyAg-oUCvWdcmTSKsiuGzbTjZC) ### 物件迴圈 使用 `for...in` 會印出物件原型 ```javascript= Object.keys(family).forEach((key) => { console.log(key, family[key]); }) ``` ### `||` 與 `??` * 真值(truthy)、假值(falsy) 在 a 值不確定的情況下,給予 100,空字串、數字0、undefined 和 null 會是 Falsy,只要是 falsy 會給予 100 ```javascript= function fn(a){ const output = a || 100; console.log(output); } fn(0); // 100 ``` ES11 之後可以用空位合併 Nullish coalescing operator (??),只有 undefined 和 null 會給予 100 ```javascript= function fn(a){ const output = a ?? 100; console.log(output); } fn(0); // 0 ``` ### 參數預設值 不過如果是使用在變數上,可以用預設值(ES6),此時只有 undefined 會給予 100 ```javascript= function fn(a = 100){ const output = a; console.log(output); } ``` ### 具名參數 給常常忘記參數傳入順序的你 ```javascript= let height, weight; function multiply({height, weight}) { return height * weight; } multiply({height: 40, weight: 50}); multiply({weight: 10, height: 90}); ``` ### 其餘參數(rest parameters) 我懶得打,[我抄的](https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part3/function_scope.html#%E4%B8%8D%E5%9B%BA%E5%AE%9A%E5%82%B3%E5%85%A5%E5%8F%83%E6%95%B8variadic%E8%88%87%E5%85%B6%E9%A4%98rest%E5%8F%83%E6%95%B8) ```javascript= function sum(...value) { let total = 0 for (let i = 0 ; i< value.length; i++){ total += value[i] } return total } console.log(sum(1, 2, 3)) //6 console.log(sum(1, 2)) //3 console.log(sum(1, 2, 3, 4)) //10 console.log(sum('1', '2', '3')) //123 console.log(sum('1', '2')) //12 console.log(sum('1', '2', '3', '4')) //1234 ``` ### optional chaining(可選串連) 不知道有沒有這個物件,又不想讓程式報錯(就會停止執行) ```javascript= const obj = { name: '小明', // family: { // name: '小明家', // obj: { // name: '111' // } // } } console.log(obj?.family?.obj?.name); ``` ## 陣列的操作 * reduce 累加 ```javascript= arr.reduce(callback[accumulator, currentValue, currentIndex, array], initialValue) ``` > 當回呼函式第一次被呼叫時,`accumulator` 與 `currentValue` 的值可能為兩種不同的狀況: > 若在呼叫 `reduce()` 時有提供 `initialValue`,則 `accumulator` 將會等於 `initialValue`,且 `currentValue` 會等於陣列中的第一個元素值 > 若沒有提供 `initialValue`,則 `accumulator` 會等於陣列的第一個元素值,且 `currentValue` 將會等於陣列的第二個元素值。 ```javascript= [0, 1, 2, 3, 4].reduce( (prev, curr) => prev + curr ); ``` * map 遍歷陣列會回穿一個新陣列 ## hoisting 關於基本概念以及為什麼要有 hoisting 可以參考:[JavaScript: 变量提升和函数提升](https://www.cnblogs.com/liuhe688/p/5891273.html) > 通常 JS 引擎会在正式执行之前先进行一次预编译,在这个过程中,首先将变量声明及函数声明提升至当前作用域的顶端,然后进行接下来的处理。 深扒 hoisting 推薦 Huli 的:[我知道你懂 hoisting,可是你了解到多深?](https://blog.techbridge.cc/2018/11/10/javascript-hoisting/) * 只有宣告會 hoisting,賦值不會 * hoisting 順序 * `function` 的宣告 * `function` 的參數 * `var` ### 參數的 hoisting ```javascript= function fn(v) { console.log(v); var v = 3; } fn(10); // 10 ``` 調整一下執行順序,注意這是想像,實際上並不會真的改變程式碼執行順序 ```javascript= function fn(v) { var v = 10; // 參數 var v; console.log(v); v = 3; } fn(10); ``` ### function 的 hoisting ```javascript= function hoistFunction() { foo(); var foo = function() { console.log(1); }; foo(); function foo() { console.log(2); } foo(); } hoistFunction(); // output: 2, 1, 1 ``` 調整後 ```javascript= // 预编译之后 function hoistFunction() { // 宣告會 hoisting,順序是 function 先 var 後 function foo() { console.log(2); } var foo; // 剩下的不會 hoisting 所以按照寫的順序 foo(); // 2 foo = function() { console.log(1); }; foo(); // 1 foo(); // 1 } hoistFunction(); ``` :::info 結論:无论是早期的代码,还是ES6中的代码,我们都需要遵循一点,先声明,后使用。 ::: ### let 跟 const 的 hoisting > let 與 const 確實有 hoisting,與 var 的差別在於提升之後,var 宣告的變數會被初始化為 undefined,而 let 與 const 的宣告不會被初始化為 undefined,而且如果你在「賦值之前」就存取它,就會拋出錯誤。 > > 在「提升之後」以及「賦值之前」這段「期間」,如果你存取它就會拋出錯誤,而這段期間就稱做是 TDZ,它是一個為了解釋 let 與 const 的 hoisting 行為所提出的一個名詞。 <!-- https://github.com/nightn/front-end-plan/blob/master/js/js-scope.md https://www.cnblogs.com/leoo2sk/archive/2010/12/19/ecmascript-scope.html https://realdennis.medium.com/%E6%87%B6%E4%BA%BA%E5%8C%85-javascript%E4%B8%AD-%E4%BD%BF%E7%94%A8let%E5%8F%96%E4%BB%A3var%E7%9A%843%E5%80%8B%E7%90%86%E7%94%B1-f11429793fcc https://ithelp.ithome.com.tw/articles/10209121 https://www.geeksforgeeks.org/difference-between-var-and-let-in-javascript/ --> ## async/sync 基本概念釐清:[非同步(Asynchronous)與同步(Synchronous)的差異](https://medium.com/@hyWang/%E9%9D%9E%E5%90%8C%E6%AD%A5-asynchronous-%E8%88%87%E5%90%8C%E6%AD%A5-synchronous-%E7%9A%84%E5%B7%AE%E7%95%B0-c7f99b9a298a),直接複製: > :x: ~~Node.js的處理方式是Sync~~ > :heavy_check_mark: Node.js的處理方式是Async > > :x: ~~Async是一次處理很多需求~~ > :heavy_check_mark: Async是接收到需求,不用一直等到需求完成再執行其他需求 ### Event queue (事件佇列) [一次只能做一件事的 Javascript](https://www.casper.tw/javascript/2017/12/07/javascript-event-queue/) * 事件堆疊會逐一執行 * 等到執行到不會立即執行的行為,就會放到 event queue,event queue 的事件在**所有事件完成前**不會被執行。 * 等到所有事件堆疊完成後 event queue 內的事件才能被觸發。 測試 ```javascript= function doWork() { var auntie = "漂亮阿姨"; (function () { console.log('打給阿姨') setTimeout(function () { console.log(auntie + '回電') }, 0) // 修改成 0 秒 })(); // ... console.log('洗碗'); return '完成事件堆疊'; } doWork(); // 執行 ``` 結果 ![event queue](https://i.imgur.com/slTY2wB.png) 在所有非同步事件如 `click`、`setTimeout`、`ajax`...,都不會立即執行這些行為,而是將這些行為放到 event queue 中,等待事件觸發後再回來執行。 ### 從 callback 到 promise 到 async/await {%youtube CTChl_DYTz0 %} [輕鬆理解 Ajax 與跨來源請求](https://blog.huli.tw/2017/08/27/ajax-and-cors/)也有提到,我自己是在看過文軒的影片之後才得到這篇,好理解 ## 物件傳值與傳參考 ### 前置觀念:除了原始型別以外,其他都是物件型別 * 原始型別 * boolean * null * undefined * string * number * symblo * 物件型別 * object * array * [typeof 的一些誤區](https://www.casper.tw/javascript/2017/12/08/javascript-typeof/#:~:text=%E5%9E%8B%E5%88%A5%E3%80%82-,Undefined%20%E8%88%87%20Null,-%E9%80%99%E5%85%A9%E5%80%8B%E5%B0%B1) ### 原始型別傳值(value),物件型別傳參考(reference) [物件連連看,兩個物件的值竟然一樣?!](https://www.casper.tw/javascript/2017/12/10/javascript-reference/) ```javascript= let a = { id: 1 }; let b = a; b.id = 2; console.log(a.id); // 2 ``` ### 複製物件 * 淺度複製 (Shallow Copy) * 手動賦值 * for...in * jQuery `$.extend` * 原生方法 `assign()` * 深度複製 (Deep Copy) * 轉字串 * jQuery `$.extend` 差異在於第一層傳值,還是所有層級皆傳值,以下例 `pet` 做範例 ```javascript= /* 原始資料 */ let auntie = { name: "陳小美", age: 36, isSingle: true, pet: { cats: 3, dogs: 2, }, }; console.log(auntie.pet.cats); // 3 ``` shallow copy ```javascript= /* 手動賦值 */ let auntie_copy = { name: auntie.name, age: auntie.age, isSingle: auntie.isSingle, pet: auntie.pet, }; // 改一下複製的值 auntie_copy.pet.cats = 9; // 會發現原始資料也被改了 console.log(auntie_copy.pet.cats); // 9 console.log(auntie.pet.cats); // 9 ``` ```javascript= /* for...in */ let auntie_copy = {}; for (const prop in auntie) { auntie_copy[prop] = auntie[prop]; } auntie_copy.pet.cats = 9; console.log(auntie_copy.pet.cats); // 9 console.log(auntie.pet.cats); // 9 ``` ```javascript= /* jQuery $.expend */ let auntie_copy = $.extend({}, auntie); auntie_copy.pet.cats = 9; console.log(auntie_copy.pet.cats); // 9 console.log(auntie.pet.cats); // 9 ``` ```javascript= /* assign() */ let auntie_copy = Object.assign({}, auntie); auntie_copy.pet.cats = 9; console.log(auntie_copy.pet.cats); // 9 console.log(auntie.pet.cats); // 9 ``` deep copy ```javascript= /* 轉字串 */ let str = JSON.stringify(auntie); let auntie_copy = JSON.parse(str); auntie_copy.pet.cats = 9; console.log(auntie_copy.pet.cats); // 9 console.log(auntie.pet.cats); // 3 ``` ```javascript= /* jQuery $.expend */ let auntie_copy = $.extend(true, {}, auntie); auntie_copy.pet.cats = 9; console.log(auntie_copy.pet.cats); // 9 console.log(auntie.pet.cats); // 3 ``` ## this :::danger 這部分還沒整理完,短期內可能也不會整理 ::: [淺談 JavaScript 頭號難題 this:絕對不完整,但保證好懂](https://blog.techbridge.cc/2019/02/23/javascript-this/) * 嚴格模式底下就都是 `undefined` * 非嚴格模式 * 瀏覽器底下是 `window` * node.js 底下是 `global` [what is THIS in javascript?](https://kuro.tw/posts/2017/10/12/What-is-THIS-in-JavaScript-%E4%B8%8A/) * `this` 是 JavaScript 的一個關鍵字。 * `this` 是 function 執行時,自動生成的一個內部物件。 * 隨著 function 執行場合的不同,`this` 所指向的值,也會有所不同。 * 在大多數的情況下, `this` 代表的就是**呼叫 function 的物件 (Owner Object of the function)**。 [javascript 的 this 到底是誰?](https://www.casper.tw/javascript/2017/12/12/javascript-this/) 如果直接調用函式,此函式的 this 會指向 window,即使 function 內在包覆著 function,但只要是直接呼叫,this 都是屬於全域。 ```javascript= window.auntie = '漂亮阿姨'; function callAuntie () { console.log('call:', this.auntie); // 漂亮阿姨 // function 內的 function function callAgainAuntie () { console.log('call again:', this.auntie); //漂亮阿姨 } callAgainAuntie(); } callAuntie(); ``` 如果 function 是在物件下調用,那麼 this 則會指向此物件,無論 function 是在哪裡宣告。 ```javascript= function callName() { console.log(this.name); } var name = "全域阿婆"; var auntie = { name: "漂亮阿姨", callName: callName, // 這裡的 function 指向全域的 function,但不重要 }; callName(); // '全域阿婆' auntie.callName(); // '漂亮阿姨',呼叫是在物件下調用,那麼 this 則是該物件 ``` 還有很多範例解釋參考 [what is THIS in javascript?](https://kuro.tw/posts/2017/10/12/What-is-THIS-in-JavaScript-%E4%B8%8A/),我懶得打 ```javascript= var obj = { func1: function () { console.log(this); // 這裡的 this 是 func1 的一個物件 var func2 = function () { console.log(this); // 這裡的 this 是全域 }; func2(); }, }; obj.func1(); ``` 小結 * this 不是 function 本身 * this 也不是 function 的 scope * this 與 function 在何處被宣告完全無關,而是取決於 function 被呼叫的方式 * this 指的是,當 function 執行時,這個 scope 的 owner * 當 function 是某個物件的 method,this 指的就是上層物件 * 全域變數的上層物件就是 window ## 閉包 循序漸進的好解釋 [[JS] 深入淺出 JavaScript 閉包(closure)](https://pjchender.dev/javascript/js-closure/)@pjchender > 一般來說function執行結束時,裡面資源(記憶體)會被釋放。 > 閉包就是function會return 一個function,常應用於當有複雜的計算的function時,一旦輸入值是一樣的,重複呼叫時不會重新計算 > 來源:[所有的函式都是閉包:談 JS 中的作用域與 Closure](https://blog.huli.tw/2018/12/08/javascript-closure/) @huli ```javascript= // 非閉包 function complex(num){ return num*num*num } complex(20) //計算一次 complex(20) //計算兩次 complex(20) //計算三次 ``` ```javascript= //運用閉包 function complex(num){ return num*num*num } function cache(func){ var ans = {} // 閉包應用的關鍵,在外面呼叫function但是ans還是會記住答案 return function() { if(ans[num]) { return ans[num] } ans[num] = func[num] // 依此例ans[20]=complex(20) return ans[num] } } const cachedComplex = cache(complex) cachedComplex(20) //計算一次,並紀錄參數=20時的答案 cachedComplex(20) //回傳答案 cachedComplex(20) //回傳答案 ``` :::danger -----------------未整理分隔線----------------以下是約莫一年前的推積灰塵區 ::: ## function * 函式只是物件的一種 * 可以將 function 儲存成變數 * 可以將 function 當成參數代入另一個 function 中 * 可以在一個 function 中回傳另一個 function * function 跟物件一樣有屬性(property) * 可以用`.`看到屬性 ### ref https://pjchender.blogspot.com/2016/03/javascriptfunctionobjects.html ## Function Expressions vs Function Declarations(function statement) ### 先看看[函式要用那種定義方式比較好?](https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part3/function_scope.html#%E5%87%BD%E5%BC%8F%E8%A6%81%E7%94%A8%E9%82%A3%E7%A8%AE%E5%AE%9A%E7%BE%A9%E6%96%B9%E5%BC%8F%E6%AF%94%E8%BC%83%E5%A5%BD%EF%BC%9F) - 多數情況下,兩者執行結果一樣 - Expressions有回傳值 - statement沒有回傳值,譬如if不能被指定成一個變數 - 不能這樣 let a = if(){}; ```javascript= // 存在很久了,可以callback function funcDeclaration() { return 'A function declaration'; } // 沒宣告不能用,var有hoisting但內容是undefined,執行會出錯 var funcExpression = function () { return 'A function expression'; } ``` ### 好處 https://www.sitepoint.com/function-expressions-vs-declarations/ - As closures - As arguments to other functions - As Immediately Invoked Function Expressions (IIFE) https://pjchender.blogspot.com/2016/05/javascriptiifesimmediately-invoked.html - 在我們建立函式的同時,這段函式就會立即被執行了! - 在這種情況下,這個 function 會被建立,但是不會被存在任何變數當中,也不會被執行。 - 透過這樣的方式,我們可以「直接執行某個函式(executing code on the fly)」,還有很重要的一點是,在 IIFEs 內所定義的變數並不會跑出去這個函式之外而干擾到程式其他的部分----->被建立在function的這個execution context 中,而不是被建立在Global Execution Context中 也許可以理解為跟*let的出現*一樣是為了程式碼更乾淨、易懂,避免污染全域環境??? --- 教科書 * [從ES6開始的JavaScript學習生活](https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/) * [IT幫鐵人賽-JavaScript之一定要了解的 Array 與方法](https://ithelp.ithome.com.tw/articles/10219475) ### Array * pop()從後面刪 * push()從後面加 * shift()從前面刪 * unshift()從前面加 * slice() * splice() * const array: only the variable name and structure type are constant.不能reassign為空array,用pop或shift慢慢刪(用function跑) [assign array](https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part3/array.html#%E6%8B%B7%E8%B2%9Dcopy%E9%99%A3%E5%88%97) 判斷是否為array ```javascript= Object.prototype.toString.call(variable) === '[object Array]' ``` ### loop Three Loop questions: 1. What do I want to repeat? -> The text function with the message! 2. What do I want to change each time? -> The y position, increasing by 20 each time. 3. How long should we repeat? -> As long as y is less than 400, all the way down. for 適用明確循環 for (start; how long; change) while 判斷為true就執行 do...while loops run code at least once— only checking the stopping condition after the first execution 先執行再判斷 --- ## Higher-order functions > When you pass a function as an argument, remember not to use parenthesis. Right: myCalculator(5, 5, myDisplayer); Wrong: myCalculator(5, 5, myDisplayer()); * 追求重複使用,撇開邏輯 * 抽象化:寫得越死就越不能重複使用,命名也不宜太過針對 {%youtube BMUiFMZr7vk%} https://medium.com/functional-javascript/higher-order-functions-78084829fff4 ```javascript= function add(x) { return function(y) { return x + y } } var add2 = add(2) var add3 = add(3) add2(4) //==>> 6 add3(6) //==>> 9 ``` > The function **add** takes a single variable x and returns a function, which in turn takes a single variable y and returns the sum of x and y. **add** is a **Function Factory**. Given a value, it creates a function, that adds a given value to a value stored in its closure. So why not just write add as **add(x, y)**? This is surely simpler. Writing functions as function factories allow you to compose other functions. We will see more of this below. And in the chapter on composition. 其實就是把複雜變簡單,只是多數範例為了好懂都用簡單的範例,讓人覺得把簡單變簡單多此一舉 :::warning ### 閉包[上移*](#閉包) ::: [非常簡單的說明](https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part3/function_scope.html#%E5%85%A7%E9%83%A8%E5%B7%A2%E7%8B%80%E5%87%BD%E5%BC%8F) ```javascript= function addOuter(a, b) { function addInner() { return a + b } return addInner() } addOuter(1, 2) //3 ``` > 內部函式可以獲取到外部函式所包含的環境值,例如外部函式的傳入參數、宣告變數等等。而內部函式又可以成為外部函式的回傳值,所以當內部函式接收到外部函式的環境值,又被回傳出去,內部函式間接變成一種可以讓函式對外曝露包含在函式內部環境值的溝通管道,這種結構稱之為"閉包(closure)"。 [Higher Order Functions - Closures:](https://medium.com/functional-javascript/higher-order-functions-78084829fff4) Creating closures should come naturally to a JavaScript programmer. If not, keep practising closures. We will be making a lot of closures in this book. You should recognise them even if it is not always explicitly mentioned. ### callback [w3cschool](https://www.w3schools.com/js/js_callback.asp) ```javascript= function myDisplayer(some) { document.getElementById("demo").innerHTML = some; } function myCalculator(num1, num2) { let sum = num1 + num2; myDisplayer(sum); } myCalculator(5, 5); ``` 有可能在`sum = num1 + num2`執行完之前就執行`myDisplayer(sum)`,所以需要callback確保`myDisplayer(sum)`最後執行, > Where callbacks really shine are in asynchronous functions, where one function has to wait for another function (like waiting for a file to load). > > Using a callback, you could call the calculator function (myCalculator) with a callback, and let the calculator function run the callback **after** the calculation is finished ![callback](https://i.imgur.com/Lkmx62q.png) > 回調(callback)提供了使用此函式的開發者一種彈性的機制,讓程式開發者可以自行定義在此函式的最後完成時,要如何進行下一步,這通常是在具有執行流程的數個函式的組合情況。實際上,回調函式實現了JavaScript中非同步(asynchronously)的執行流程,這使得原本只能從頭到底(top-to-bottom)的程式碼,可以在同時間執行多次與多種不同的程式碼。[出自:從ES6開始學習JavaScript](https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part3/function_scope.html#%E5%9B%9E%E8%AA%BFcallback) #### Codecademy - The .forEach() Method ![.forEach() Method](https://i.imgur.com/43RXhgH.png) ```javascript= groceries.forEach(groceryItem => console.log(groceryItem)); ``` 這個 callback 函式(.forEach()括號內的函式)將會把 Array 中的每一個元素作為參數,帶進本 callback 函式裡,每個元素各執行一次 1. groceries `.forEach()` calls the forEach method on the groceries array. 1. `.forEach()` takes an argument of callback function. **Remember, a callback function is a function passed as an argument into another function.** 1. `.forEach()` loops through the array and executes the callback function for each element. During each execution, the current element is passed as an argument to the callback function. 1. The return value for `.forEach()` will always be undefined. [你懂 JavaScript 嗎?#23 Callback](https://cythilya.github.io/2018/10/30/callback/) ### 常見使用Map、Reduce https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part3/array.html#%E8%BF%AD%E4%BB%A3 https://fred-zone.blogspot.com/2017/01/javascript-mapreduce.html https://ithelp.ithome.com.tw/articles/10235812 ## Object [ref:Codecademy](https://www.codecademy.com/courses/introduction-to-javascript/lessons/objects/exercises/pass-by-reference) > when we pass a variable assigned to an object into a function as an argument, the computer interprets the parameter name as pointing to the space in memory holding that object. As a result, functions which change object properties ```javascript= let spaceship = { homePlanet : 'Earth', color : 'red' }; let tryReassignment = obj => { obj = { identified : false, 'transport type' : 'flying' } console.log(obj) // Prints {'identified': false, 'transport type': 'flying'} }; tryReassignment(spaceship) // The attempt at reassignment does not work. spaceship // Still returns {homePlanet : 'Earth', color : 'red'}; spaceship = { identified : false, 'transport type': 'flying' }; // Regular reassignment still works. ``` ```javascript= let spaceship = { 'Fuel Type' : 'Turbo Fuel', homePlanet : 'Earth' }; // Write your code below let greenEnergy = (obj) => { obj = { 'Fuel Type':'avocado oil' //不會改變 } } let remotelyDisable = (obj) => { obj.disabled = true //會改變 } ``` - scope作用域=>變數的生存範圍 - 作用域會往上尋找變數(形成「作用域鏈scope chain」:注意這個function在哪個scope是以被宣告的位置為主,而非被呼叫的位置) - 注意:如沒有宣告變數,JS會自動宣告為全域變數 - ES5:以function為單位,內部宣告的變數外部無法讀取

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully