[JS奇怪的世界]No.21 框架小叮嚀:預設值

第一個框架的小叮嚀

接下來將針對框架做一個小觀念叮嚀,這邊課程講解的是 jQuery,為什麼會拿 jQuery 來講解呢呢?以前最熱門的框架非 jQuery 莫屬,舉凡動畫效果等等都是由 jQuery 一手包辦,並不用說瀏覽器適應問題,所以這章節拿 jQuery 來作範例再適合不過了。

所以這次課程將結合前面學的參數預設值,還有執行環境全域環境等觀念,試著去了解 jQuery 程式碼。

課程建立了三個檔案做範例,假設 lib1 及 lib2 都是由別人所撰寫的第三方套件。

  • lib1.js
  • lib2.js
  • app.js // 我們自己的核心 js

lib1.js 內容是 ↓

1
var libraryName = 'Lib1';

lib2.js 內容是 ↓

1
var libraryName = 'Lib2';

那如果同時載入時會發生什麼事情?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="lib1.js"></script>
<script src="lib2.js"></script>
<script src="all.js"></script>
</head>
<body>
</body>

</html>

我們試著在 all.js 寫入 console.log(libraryName);,這時候它會吃到誰?

答案是吃到 lib2.js,為什麼?首先在 HTML 中 lib1.js 是第一個載入 var libraryName = 'Lib1'; 的,後來第二行 lib2.js 載入了 var libraryName = 'Lib2';,而 var libraryName 目前所建立的環境是全域執行環境,所以代表著 libraryName 是全域變數,所以當 lib2 的 libraryName 建立時才會導致蓋掉原本的 lib1.js 的 libraryName

那該如何解決?其中一個方法使用 ES6 中的 let

lib1.js 內容是 ↓

1
var libraryName = 'tomy';

lib2.js 內容是 ↓

1
var libraryName = 'jack';

結果會變什麼?

redeclaration

結果會是 tomy,而且還會出現一個錯誤 SyntaxError: redeclaration of let libraryName,這句錯誤是在說 libraryName 被重複命名了,也就是說因為 ES6 let 的特性,所以才不會因為 lib2.js 後加載導致 libraryName 被覆蓋掉。

另外課程上也有寫另一種不使用 ES6 的方式

lib2.js 內容 ↓

1
window.libraryName = window.libraryName || 'lib2';

意思是在檢查當全域環境下是否已經有了 libraryName 這個變數,如果有那麼就不做任何動作,若沒有在建立新的 libraryNamelib2

結果呢?

window

這樣就可以知道當若我們不使用 ES6 的時候可以這樣做,避免衝突問題,這也是人家所謂的全域變數汙染,而這個做法在課程上也有一個專有名詞「**檢查全域命名空間 (global namespace)**」,當然我是比較頃向使用 ES6。

圖源

JavaScript 全攻略:克服 JS 奇怪的部分