iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 7
0
Modern Web

認真學前端開發 - 以 TodoList 為例系列 第 7

Day07 - 讓 IIFE 來當範疇的守門員

不知道有沒有人有這樣的經驗,寫了一段 javascript 自己測試覺得沒問題,但放上線卻整組爛光光,最後 debug 很久才發現原來是自己的程式污染到 Global Scope (window 的部分)
所以寫 javascript 會有前輩阻止我們寫出像是這版的 Todo List
因為所有的 variable 都暴露在外面了,那如果你的同事去做另一項功能然後使用了相同的名字,最後上線前再各自把 script 放到 html 上,結果喝完慶功宴回來發現功能不能用,那會多尷尬呀!

今天來學學用什麼方法讓 todo list 比較安全吧!

IIFE

直接丟 MDN

重點整理

  • 立即函示必須是匿名的函式
    • 如果給個名字是不是又污染了 XD
  • 寫法像這樣
    • MDN 有其他寫法可以參考
小括號把 function 包起來
(function(){})()
外面有個小括號指定要執行
  • 這樣的設計模式就是把變數全部鎖在這個 匿名函式

來把 Todo List 改成比較好的寫法吧

html 的部分先拿掉 onclick

  <div class="header">
    <h2>待辦清單</h2>
    <input type="text" id="todo-input" placeholder="待辦事項">
    <button id="addTodo" class="addBtn">新增</button>
  </div>

  <ul id="todo-list">
    <li>第一個工作<span class="close">x</span></li>
    <li class="checked">先完成這個<span class="close">x</span></li>
  </ul>

開始做 javascript 部分

先將整包用 IIFE 包起來

代碼佔太多行數就不貼上來了source code

比較先前的可以打開 F12 (inspector)在 console 上打上

修改前 myInput 會出現

> myInput
< <input type=​"text" id=​"todo-input" placeholder=​"待辦事項">​

修改後

> myInput
< Uncaught ReferenceError: myInput is not defined at <anonymous>:1:1

接下來把原本新增的 event 註冊上去

var todoButton = document.querySelector('#addTodo');
todoButton.addEventListener('click', addTodo, false);

Hoisting

如果看了 source code 會發現 addTodo 沒被定義在註冊點擊事件前面,卻可以這樣用,很多語言中這樣寫會出錯(不過建議少這樣寫,剛玩 javascript 可能看到會誤會甚至發怒喔!)

這個有名字的函式 (function declaraction) 的特性是

  • 名字會被拉升到前面 (hoisting)
  • 有名字

既然提到 Hoisting 不免俗就要來看看 Variable 中的 Hoisting (Hoisting 中的 Variable)

Variable

試試跑以下 code 在 console

#1

console.log(mySpecialList)
Uncaught ReferenceError: mySpecialList is not defined
    at <anonymous>:1:13

#2

console.log(mySpecialList); var mySpecialList = 'my list';
undefined

#1 會噴 Exception 但 #2 會顯示 undefined 並不會噴錯誤
原因是 #1 被執行的時候記憶體中沒有 mySpecialList 這個 variable
而 #2 的時候記憶體中會有 mySpecialList 這個 variable 但在
console.log(mySpecialList) 的時候還不會被賦值

如果回到 TodoList 上會發現什麼!

var i; 這個被出現兩次,但實質上只會跑一次

再來看更危險的 for-loop 中的 var

for (i = 0; i < myNodelist.length; i++) {
  var span = document.createElement("SPAN");
}

span 這個 variable 會被拉升到最前面,如果不注意會以為是 for-block 裡面的 variable 呢!

所以很多人提倡說只要是 var 會被拉升到前面的,我們就在最一開始把 var 給定好
因為 code 很多所以不貼上來了

改完的示意 code

(function(){
  var i,
      todoButton,
      myNodelist,
      span,
      close,
      list,
      myInput,

  todoButton = document.querySelector('#addTodo');
  todoButton.addEventListener('click', addTodo, false);

})()

上一篇
Day06 事件處理
下一篇
Day08 - 在 TodoList 上加新功能
系列文
認真學前端開發 - 以 TodoList 為例30

尚未有邦友留言

立即登入留言