#### Introduction to JavaScript

Spring 2019 。 Ric Huang
---
在學習完 HTML & CSS 之後,
你應該是有能力可以刻出一個靜態網頁
(雖然 CSS 的 state selector
也是可以做出一定程度的動態網頁啦!)
---
現代的動態網頁 (各種跟使用者 I/O 的互動),
幾乎都是使用 JavaScript 寫的
但為了接下來理解如何
利用 JavaScript 製作出動態網頁,
我們必須先瞭解何謂
**DOM (Document Object Model)**
---
### DOM (Document Object Method)
([wiki](https://en.wikipedia.org/wiki/Document_Object_Model)) …is a cross-platform and language-independent application programming interface that treats an HTML, XHTML, or XML document as a tree structure wherein each node is an object representing a part of the document.
---

---
### Let's HACK it!

----
* 開啟[台大校長室首頁](https://www.ntu.edu.tw/administration/president.html)
* 打開 **開發人員選項 -> 檢視元素**
* 滑鼠在頁面滑動,看是否可以看得出 DOM structure?
* 滑到管校長玉照,click on its parent \<div> element (有看到旁邊多了一個 $0 嗎?)
* 打開 "console", 輸入 $0 試試看!
* (先到網路上選一張圖片,複製連結) 輸入 $0.innterHTML = "<img src='你的圖片連結'... 照著原先的打"
* (選到 "校長 管中閩博士" 的 \<p>) 用 $0.innterText 改改看!
---
## Did you really HACK it??
---
### Not really...
剛剛改的是你瀏覽器(前端)收到的 HTML (i.e. local 端),一但 reload, 從 server 端 (i.e. 台大計中) 重新載入網頁,剛剛的修改就都不見了!
---
不過,如果你寫了一個網頁服務程式,放在自己的伺服器,讓使用者在他的瀏覽器進行互動的過程中 (如:滑鼠點按、填資料送出等),將「動作」送至伺服器,然後你的網頁程式「聽到」這個動作「事件」後,送回對應的網頁更新(部分)腳本,使用者就會看到更新的網頁了!
---
### JavaScript 就是去 listen event <br>來操作 DOM 的內容,<br>以達到動態網頁的目的
---
### 不過,在介紹JavaScript語法之前,<br>讓我們來了解一下 JavaScript 精彩的(黑)[歷史](https://auth0.com/blog/a-brief-history-of-javascript/)
* Possibly the most hated language in the world
----
### A new web language was born
* Year 1995 (rise of IE; Netscape/Sun/Microsoft)
* Brendan Eich created it in a few weeks
* 披著 Java 皮,流著 Scheme (first-class function) / Self (prototype-based)的血
----
### 醜小鴨變天鵝
* 短時間生產出來的畸形兒
* ECMA standardization (ES): 1 (1997), 2 (1998)
* ES3: the first big change (1999)
* ES4: the unborn child
* ES3.1 (2008) -> ES5 (2009)
----
### ES6 (aka. ES 2015): The Modern JS
* let/const
* arrow function
* class
* promise (to relieve callback hells)
* generator
* binary/octal literals
----
### ES7 and Beyond
* ES7 (aka. ES 2016)
* minor changes (e.g. exponential **)
* ES2017
* async/await (to improve "promise")
* shared memory and atomics
* ES2018
* asynchronous iteration
* generator arrow functions
----
### What's next?
* Inter-platform operability
* Native support on VM
* (Already is) Full-stack language
---
### JavaScript。與 C++ 比較
----
### 相異之處
* 弱型別,所有的變數都是 var (or let/const)
```javascript
var a = “38”;
var b = false;
console.log(a + !b);
```
* Statement 的後面可以不用加 “;”
* 數字都是 “double“
```javascript
0.1 + 0.2; // = 0.30000000000000004
```
* 除了 ==, 還有 ===
* 字串可以用 ' ' or " "
----
### Prototype-Based object construction
不用先定義 class 即可建置物件,且一旦一個物件被建置好,後續的物件可以用它來當作原型來建置類似的物件
----
### First-Class Functions
也就是說 functions 被當成是一般的變數(物件),可以當成其他 function 的參數或是回傳值,也可以被 assigned 給別的變數
---
### JavaScript Basics
* console.log()
* Types/Variables/Objects
* Function
* Array
* Control statements
* DOM manipulation & Event listening
---
### console.log
* 是你 debug 的好朋友,會將訊息印在 “console”
(e.g.) In Chrome on Mac, press “command-option-i”
```javascript
var a = 1;
console.log(a);
```
---
### Types/Variables/Objects
* JavaScript 只有五種內建型別(primitive types),**其他都是物件(objects)**
| 型態 | 範例 |
|-----| ---- |
| Undefined (未定義) | undefined |
| Null (空值) | null |
| String (字串) | "哎呀" |
| Boolean (布林值) | true, false |
| Number (數字) | 3.1415926 |
----
### In JS, almost everything is an object
* Object in JavasScript is represented as:
```javascript
{ property: value, ... }
```
```javascript
var me = { name: "Ric", age: 18 }
```
* Note: No need to define "type" or "var" for "name" and "age"
----
### 三種產生 object 的方法
1. Object literal
```javascript
var a = { name:"Ric", score:100 };
```
2. “new” operator
```javascript
var b = new Date;
```
3. Constructor function
```javascript
function Student(name, score) {
this.name = name;
this.score = score;
}
var c = new Student(“Ric”, 100); // return this
```
* What happens for “var d = Student(“Nacy”, 20);”?
// The returned type of Student() is "undefined"
----
### 不要把五種內建型別宣告成 object
```javascript
var a = new Number(3); // 不建議
var b = Number(3); // What's the difference?
console.log(a === b); // false
```
```javascript
var a = 3; // a is a primitive
var b = Number(3); // b is a primitive
var c = new Number(3); // c is an object
```
----
### The keyword “Object” defines an object
```javascript
var o = new Object;
```
----
### “prototype-based” object construction
```javascript
var o = new Object;
console.log(o);
// No need to define "name" and "score" in advance
o.name = "Ric";
o.score = 100;
var o2 = new Object;
console.log(o);
console.log(o2);
```
----
#### Primitive variable assignment makes a “copy”
```javascript
var a = 3;
var b = a; // {a, b} = {3, 3}
b = 4; // {a, b} = {3, 4}
a = 5; // {a, b} = {5, 4}
```
----
#### Object variable assignment pass the “reference” to the object’s address
```javascript
var i = { a:3 };
var j = i;
j.a = 4; // i.a = 4
i.a = 5; // j.a = 5
```
---
### Function as an Object
* Functions in JavaScript is “first-class”
// Function as an object (i.e. constructor function)
* var f = function add(a, b) { return a + b; };
* Note: Function 的 arguments 沒有必要加上 “var”
NOT "function add(var a, var b)"
* Function can be anonymous // recommended
```javascript
var add = function(a, b) { return a + b; };
```
----
### Function assignment
* 如同 object assignment (i.e. pass by reference)
```javascript
// f is an reference to add
var f = function add(a, b) { return a + b; };
// print out the returned value of f(3,4)
console.log(f(3,4));
// print out f itself
console.log(f);
// Error (why?)
console.log(add);
```
----
### Return of a function
* By default, the return value of a function is "undefined", unless call by "new" (return this)
```javascript
var f = function(a, b) { return a + b; };
f(3,5);
f(f(1,2),3);
```
----
### Return a function
```javascript
var f = function(s) {
return s?
function(a,b) { return a+b; }:
function(a,b) { return a-b; }
};
var f1 = f(true); f1(3,5);
var f2 = f(false); f2(3,5);
```
----
### Methods in Objects
* Recall: prototype-based object construction
```javascript
var a = { name:"Ric", score:100 };
a.gender = "Male";
```
* Since function is also an object, we can define “method functions” in an object as:
```javascript
var a = {
name:"Ric", score:100,
report: function() {
return this.name + " got " + this.score;
}
};
a.report(); // Ric got 100
```
----
### Define a method afterwards
```javascript
a.isPass = function() {
console.log(this.score >= 60? “Yes”: “No”);
};
a.isPass() // Yes
```
----
### Immediately Invokable Function Expression
* When a function is used only once, we can declare it anonymously and evoke it immediately
```javascript
(function() {
... some statements
})();
```
---
### Test yourself #1 (Any errors?)
```javascript=
function f(a) { console.log(a); }
f(0);
var b = f;
b;
b(10);
b("Hello");
var c = f(20);
c; // undefined
c(30); // Error!
```
----
### Test yourself #2 (Any errors?)
```javascript=
var f = function add(a, b) { return a + b; };
add(10, 20); // Error!
f(20, 30);
var g = f;
g(30, 40);
var h = add; // Error!
h(40, 50); // Error!
```
----
### Test yourself #3 (Any errors?)
```javascript=
var f = function add(a, b) { return a + b; };
var g = add; // Error
var h = function add(a, b) { return a + b; };
var i = function add(a, b, c) { return a + b + c; };
var f = "Hello"; // overloading f
```
----
### Test yourself #4 (Any errors?)
```javascript=
var f = function pp() { ... }
var g = f;
var f = function qq() { ... }
console.log(f); // qq
console.log(g); // pp
```
---
## Array Objects
----
### To define an array
1. Using array literal
```javascript
var students = [ "John", "Mary", "Ric" ];
```
2. Using new Array // not recommended
```javascript
var students = new Array("John", "Mary", "Ric");
```
----
### Data in an array can be of any types
```javascript
var a = [ "Ric", 100, function() { return "Hello!"; } ];
a[2](); // Hello!
```
----
### ”length” property and “push” method in Array
```javascript
// initialized as an empty array
var s = [ ];
s.push("John"); // recommended
s[s.length] = "Mary"; // length is now 2
s[3] = "Ric"; // OK, but create an “undefined” in [2]
```
----
### Array is a special kind of object
```javascript
var students = [ "John", "Mary", "Ric" ];
typeof students; // object
Array.isArray(students); // true
```
----
### Array elements MUST BE accessed by numbers
* 雖然一些 object 的行為看起來很像 array, 但嚴格來說,他們是不一樣的
```javascript
var a = { name:"Ric", score:100 };
a["name"]; // "Ric"
a[0]; // undefined
Array.isArray(a); // false
```
----
### Array or Object
* Array is an object.
```javascript
var s = [];
s[0] = "John";
s["Name"] = "Ric";
console.log(s); // ["John", name: "ric"]
Array.isArray(s); // true
```
---
### Control statements in JavaScript are pretty much the same as in Java/C/C++
* Comparison in JavaScript use "=\==" and "!\=="
* "==" 跟 "!=" 會雞婆地幫你做型別轉換
"5" == 5; // = true
null == undefined; // = true
* 更多令人崩潰的型別轉換/比較會在下一章補充
---
### Variable Hoist
* Variable 定義的位置會自動抬升到最前面
* 以下兩種寫法是一樣的(雖然前者不太正常):
```javascript
a = 1;
var a = 2;
```
```javascript
var a = 1;
a = 2;
```
----
### Function Hoist
* Function declaration 定義的位置會被抬升到最前面
```javascript
sum(3,5); // This is OK!
function sum(a, b) { return a + b; };
```
* 但用 expression 定義的 function 變數則不會被抬升
=> 如果在定義之前就被使用,就會是 error
```javascript
sum(3,5); // Error
var sum = function(a, b) { return a + b; };
```
---
### Variable Scope
* 事實上,“var” 沒有寫也會過,只是會被視為全域變數 (global variable)
* 此外,”var” 如為區域變數,其範圍並非 block, 而是 function scope
```javascript
function() {
for (var i = 0; i < 10; i++)
console.log(i);
}
// 等同於
function() {
var i;
for (i = 0; i < 0; i++)
console.log(i);
}
```
----
### Variable Scope
* 在同一個範圍內重複用 “var” 宣告同名字的變數,後者會被無視,而只進行 assignment
```javascript
var a = 0;
{ var a = 10; } // 仍屬同一範圍之 'a'. a = 10 now
var b = function() { var a = 20; }
b(); // local 'a' 並非 global 'a'. 所以 a 仍然為 10
```
---
### ”let” and “const”
* 2015 年發表的 ES6 版本加入了 “let” 跟 “const”
----
### “let” 跟 C/C++ 的變數一樣,採取 block scope
* 同一個 scope 不能宣告相同名稱的變數
* 不能在宣告變數之前就使用 (i.e. 用 let 宣告的變數不會被抬升 (hoist) 到 scope 的最前面)
* 在 global scope 用 let 宣告的變數並不是真正的 global variable
==> 並不會變成 “window” 這個全域物件底下的屬性,因此,像是用 module 載入的程式碼並看不到這個 global scope 的 let 變數
----
### “const” 亦跟 C/C++ 一樣,表示 “read-only” 的常數變數
* 養成習慣,多多使用 const
---
### DOM Manipulations
* 選擇節點
* 瀏覽節點
* 增減節點
* 修改節點內容
* 事件監聽綁定
----
#### 在一個瀏覽器的頁面 “window” 是唯一的全域物件,<br>而 “document” 是它的一個屬性

#### 如前所述,所謂的動態網頁就是在 event 觸發之後,選擇某個/某些 DOM 節點,然後改寫其內容或是周邊的節點 (node/element)
---
### 選擇節點
* 從 top level (i.e. “document”) 尋找 DOM nodes
```htmlembedded
<div id="target"></div>
<div class="a-class"></div>
```
1. 回傳 unique DOM node
```javascript
var target = document.getElementById("target");
```
2. 回傳一個 array of DOM nodes
```javascript
var arr = document.getElementsByClassName("a-class");
var arr2 = document.getElementsByTagName("div");
```
3. 用 CSS 的一部份 selector 來選取
```javascript
var target = document.querySelector("#target");
var arr = document.querySelectorAll(".a-class");
```
---
### 瀏覽節點
* 從某個 DOM node 找到下一層的節點
(These are properties, not functions)
```javascript
var arr = parentNode.children;
var element1 = parentNode.firstElementChild;
var element2 = parentNode.lastElementChild;
var count = parentNode.childElementCount;
```
---
### 增減節點
* 在 document 底下 或是 **某個節點前後** 增減節點
```javascript
var newElement = document.createElement(“div”);
var newText = document.createTextNode(“Hello!”);
```
```javascript
// become the last child
var appendedNode = parentNode.appendChild(childNode);
// removed from parent
var removedNode = parentNode.removeChild(childNode);
// insert before refNode
var insertedNode = parentNode.insertBefore(newNode, refNode);
// replace child node
var replacedNode = parentNode.replaceChild(newNode, oldNode);
```
---
### 修改節點內容
* 修改節點內容、屬性、樣式... 等
#### These are properties, not functions
```javascript
// get the serialized HTML code for all of its children
const childrenHTMLCode = thisNode.innerHTML;
// replace all of its children using the HTML code
thisNode.innerHTML = childrenHTMLCode;
// modify CSS style
thisElement.style.color = “red”;
// modify properties
thisElement.className = “new-class1 new-class2”;
thisElement.classList.add(className);
thisElement.classList.remove(className);
```
---
### 事件監聽綁定 (方法一) -- addEventListener()

----
### 事件監聽綁定 (方法一)
```htmlembedded
<button id="target">是個按鈕</button>
```
```javascript
var targetElement = document.getElementById("target");
targetElement.addEventListener(
"click",
function() {
// ..做一些事,任何事,你希望按鈕按了要幹麻?
alert('你希望按鈕按了要幹麻?');
}
);
```
----
### 事件監聽綁定 (方法二) -- GlobalEventHandlers \[[ref](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers)]
* target.onclick = functionRef;
```htmlembedded
<p>Click anywhere in this example.</p>
<p id="log"></p>
```
```javascript
let log = document.getElementById('log');
log.onclick = inputChange;
function inputChange(e) {
//.. some something here
}
```
----
### 事件監聽綁定 (方法三) -- <br>As a tag attribute
* List of global attributes \[[ref](https://developer.mozilla.org/en-US/docs/Glossary/Global_attribute)]
```javascript
<div class="myClass" onclick="clickHandler()">
```
---
## End
{"metaMigratedAt":"2023-06-14T20:19:53.032Z","metaMigratedFrom":"YAML","title":"Introduction to JavaScript (02/27)","breaks":true,"slideOptions":"{\"theme\":\"beige\",\"transition\":\"fade\",\"slidenumber\":true}","contributors":"[{\"id\":\"752a44cb-2596-4186-8de2-038ab32eec6b\",\"add\":16578,\"del\":2604},{\"id\":\"9a7bf29c-b92e-4280-bcb4-968a7895b32e\",\"add\":3,\"del\":0},{\"id\":\"a202b02b-072b-4474-be14-c5a3f8932dbb\",\"add\":5,\"del\":16}]"}