不知道有沒有人有這樣的經驗,寫了一段 javascript 自己測試覺得沒問題,但放上線卻整組爛光光,最後 debug
很久才發現原來是自己的程式污染到 Global Scope
(window 的部分)
所以寫 javascript
會有前輩阻止我們寫出像是這版的 Todo List
因為所有的 variable 都暴露在外面了,那如果你的同事去做另一項功能然後使用了相同的名字,最後上線前再各自把 script
放到 html
上,結果喝完慶功宴回來發現功能不能用,那會多尷尬呀!
今天來學學用什麼方法讓 todo list 比較安全吧!
直接丟 MDN
重點整理
小括號把 function 包起來
(function(){})()
外面有個小括號指定要執行
匿名函式
內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);
如果看了 source code 會發現 addTodo
沒被定義在註冊點擊事件前面,卻可以這樣用,很多語言中這樣寫會出錯(不過建議少這樣寫,剛玩 javascript
可能看到會誤會甚至發怒喔!)
這個有名字的函式 (function declaraction) 的特性是
既然提到 Hoisting
不免俗就要來看看 Variable 中的 Hoisting (Hoisting 中的 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);
})()