# JavaScript
<p style="text-align: right;">組員:陳俊宇、張育豪</p>
<p style="text-align: right;">張祐禎、張嘉榮</p>
<!-- .slide: data-transition="slide" -->
---
# Outline
* 背景與簡介
* Javascript在前端中的定位
* 性質
* 幾個 Library, Framework 介紹
* 實作
---
# 背景與簡介
<!-- .slide: data-transition="slide" -->
----
## 發明JavaScript的原因
### 從跑龍套到挑大樑
----
## Brendan Eich(1961年7月4日~)
#### JavaScript 語言創始人

* 公司要求做出掛載在瀏覽器上的小工具
<!-- ## 開發動機? -->
<!-- * 作為瀏覽器內置的腳本語言,為網頁開發者提供操控瀏覽器的能力,目前為唯一所有瀏覽器通用的腳本語言,幾乎全世界的網頁都使用Javascript。 -->
----


----

### JavaScript推出不久後
### 微軟公司為Internet Explorer 3瀏覽器推出了JScript
----

### 歐洲電腦製造商協會(ECMA)以JavaScript語言為基礎制定了ECMAScript標準規範ECMA-262
<!-- .slide: data-transition="slide" -->
---
# Javascript
# 在前端網頁中的定位
<!-- .slide: data-transition="slide" -->
----
### 大雜燴
```htmlembedded=
<html>
<head>
<title>This is title you know</title>
<style>
.menu {
background-color: black;
color: white;
padding: 10px;
vertical-align: top;
width: 100px;
list-style-type: none;
}
.menu a {
color: white;
text-decoration: none;
}
</style>
<script type="text/javascript">
function show(id) {
document.getElementById(id).style.visibility = 'visible';
}
function hide(id) {
document.getElementById(id).style.visibility = 'hidden';
}
</script>
</head>
<body onload="JavaScript:hide('popup1')">
<ul onmouseover="show('popup1');" onmouseout="hide('popup1')" style="position:absolute; left:100px; top:20px">
<li id="menu1" class="menu">menu1</li>
<ul id="popup1" class="menu">
<li><a href="JavaScript:alert('I'm 1.1');">menu 1.1</a></li>
<li><a href="JavaScript:alert('I'm 1.2');">menu 1.2</a></li>
</ul>
</ul>
</body>
</html>
```
<!-- .slide: data-transition="slide" -->
----
## 所以 JavaScript 在網頁到底佔了什麼角色?
----

<!-- .slide: data-transition="slide" -->
----
## 操作方法
## 瀏覽器環境提供
* BOM
* DOM
----
## BOM?
BOM (Browser Object Model,瀏覽器物件模型)
提供JavaScript與瀏覽器互動的API
* 開啟/關閉視窗
* 改變視窗大小
* 計時器與取得網址..等
----
## 架構圖

----
## window下的global variable
```javascript=
var a = 10;
console.log( window.a ); // 10
window.alert(message);
alert("安安");
window.confirm(); //確定/取消
window.prompt(); //開放式問答
```
----
## DOM?
<!-- .slide: data-transition="slide" -->

----
## 一個將 HTML 文件以樹狀的結構來表示的模型
<!-- .slide: data-transition="slide" -->
----
```htmlembedded=
<html>
<head>
<title>一個簡單的網頁</title>
</head>
<body>
<h1>這是標題</h1>
<p>這是一個<i>簡單</i>的網頁</p>
</body>
</html>
```
<!-- .slide: data-transition="slide" -->
----

----
## DOM API
### 定義了...
* 存取
* 改變 HTML 架構、樣式、內容的方法
* 對節點綁定的事件
<!-- .slide: data-transition="slide" -->
----
## Node Retrieve Method
```javascript=
// 根據傳入的值,找到 DOM 中 id 為 'abc' 的元素。
document.getElementById('abc');
// 針對給定的 tag 名稱,回傳所有符合條件的 NodeList 物件
document.getElementsByTagName('box');
// 針對給定的 class 名稱,回傳所有符合條件的 NodeList 物件。
document.getElementsByClassName('apple');
// 針對給定的 Selector 條件,回傳第一個 或 所有符合條件的 NodeList。
document.querySelector('xxx');
document.querySelectorAll('xxx');
```
----
## Example
```htmlembedded=
<h1 id="greet"></h1>
<script>
document.querySelector('#greet').textContent = 'Hello World!'
</script>
```
<!-- .slide: data-transition="slide" -->
---
# 性質
<!-- .slide: data-transition="slide" -->
----
## 型態
----
## 型態
* 動態(Dynamically-typed)語言
* 變數型態無須宣告,型態由值所決定
```javascript=
var number = 10; //Number
var string = "hello"; // String
var bool = true;// Boolean
var array = []; // Object
```
----
## 宣告方式
* var
* let (ES6/ES2015時提出)
* const (ES6/ES2015時提出)
----
* 基本型態:
* Number (數字)
* String (字串)
* Boolean (布林值)
* Function (函式)
* Object (物件)
* 特殊型態:
* undefined (未定義)
* null (空)
----
### Number
<!--
* Javascript支援基本的運算子(+、-...)
* 提供特殊Object Math來進行進階的數學運算
* 有個特殊的數字,叫做 NaN (「Not a Number」,「非數字」的簡稱)
* parseInt -> 參數一:要轉換的變數 參數二: 進位制
* isNaN -> 判定是否為Number
*
NAN不等于任何值,包括它自身
-->
* 數值沒有區分Integer與Float,合稱為Number
```javascript=
var a = 1;
var b = 2;
var c = Math.sin(Math.PI); // 0
parseInt("5", 10);
isNaN(1); // false
isNaN('a'); // true
Number('ABC'); //把ABC字串轉成Number -> NaN
a/0; // 正數除以0 -->Infinity
-a/0; // 負數除以0 --> -Infinity
```
----
### Number分數相加
由於Javascript採用雙精度浮點數的關係,在分數操作上的結果可能會跟想像的結果不同。主要是在數值轉換回二進位,再從二進位轉回十進位時所造成的誤差。
```javascript=
var a = 0.1;
var b = 0.2;
console.log(a+b); // 0.30000000000000004
```
[參考資料](https://github.com/camsong/blog/issues/9)
----
### String
<!--
* length -> 返回字串長度
*
-->
```javascript=
var text = 'Programming Language';
//一些基本的字串操作
text.length; // 11
text.replace('Language', 'LALALA'); // Programming LALALA
text.toUpperCase(); // PROGRAMMING LANGUAGE
String(123);//'123'
//模板字串符
var test1 = "a
b
" // Error!
var test2 = `a
b
c
` // Won't cause Error
var a = 'Wu'
var b = 'Lai'
var result = 'a'+' hates '+'b' //Wu hates Lai
var result = `${a} hates ${b}` // //Wu hates Lai
```
----
### Boolean
<!-- Boolean() -> 把值轉型為boolean -->
```javascript=
Boolean(false) // false
Boolean(0) // false
Boolean('') // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(NaN) // false
```
<!-- 除了以上的值,其餘的都會被轉為true -->
----
### undefined
* 只要一個變數在初始的時候未給予任何值的時候,Javascript會給此變數一個預設的值undefined
```javascript=
var a;
let b;
const c; //Error !
typeof a;// undefined
typeof b;
```
----
### 弱型態
* number、string與boolean,會在必要的時候自動型態轉換為對應的包裹物件
```javascript=
'6' + 2 // '62'
2 + '6' // '26'
'6' - '2' // 4
'6' - 2 // 4
'6' * '2' // 12
'6' / '2' // 3
'ABC' / '2' //NaN
1 + true // 2
1 + false // 1
1 == true // true
// 要避免型態強制轉換,要用三等號運算子(絕對等於):
1 === true // false
```
----
## var、let、const的差別在哪?
----
## 為何要用let呢?
----
### Var造成的相關問題
1. 變數外洩
2. 變量提升(Hoisting)
3. 變數可重複宣告
----
<!-- 在var 的世界裡
如果要區分全域(global)與區域(local)
只有用function 來區分 -->
### 1. 變數外洩
```javascript=
var a = 100;
function test(){
for (var b = 0; b < 10; b++){
var c = 1;
}
console.log(a); //100 -> global variable
console.log(b); //10 -> test 的 local variable
console.log(c); //1 -> test 的 local variable
}
test();
console.log(b); // Error!
```
----
### 變量提升(Hoisting)
* 可以先使用在宣告變數(函數)
```javascript=
y = 1;
var y;
var x = 'outer';
function test(args) {
if (args) {
var x = 'inner';
return x;
}
return x;
}
console.log(test(false)); // Answer??
console.log(test(true)); // Answer??
```
----
### 變量提升(Hoisting)
```javascript=
var x = 'outer';
function test(args) {
if (args) {
var x = 'inner'; // 作用域是整個function
return x;
}
return x; //被重新定義,因为第4行聲明被提升
}
console.log(test(false)); // undefined
console.log(test(true)); // inner
```
----
### 變量提升(Hoisting)
```javascript=
var x = 'outer';
function test(args) {
var x;
if (args) {
x = 'inner'; // 作用域是整個function
return x;
}
return x; //被重新定義,因为第4行聲明被提升
}
console.log(test(false)); // undefined
console.log(test(true)); // inner
```
----
### 4頁前的例子可改為
```javascript=
var a = 100;
function test(){
var b;
var c;
for (b = 0; b < 10; b++){
c = 1;
}
console.log(a); //100 -> global variable
console.log(b); //10 -> test 的 local variable
console.log(c); //1 -> test 的 local variable
}
test();
console.log(b); // Error!
```
----
### 變數可重複宣告
```javascript=
var a = 1;
var a = 2;
var a = 3;
```
----
### 以let宣告就不會有上述問題瞜!
----
### let
ES6所提供的新宣告方式,有block scope的特性,語法與var相近,但無上述問題存在。
```javascript=
for(let i =0 ;i<10;i++){
let a = 0;
let a = 1; //Error!! 不可重複宣告
}
console.log(i); //Error!!! 有block scope特性,無法access for回圈內的變數。
```
----
### const
ES6所提供的新宣告方式,一樣有block scope的特性,宣告後assign的值不可更改。
```javascript=
for(let i = 0;i<10;i++){
const a = 0;
const b; //Error! const宣告值不可不assign一個值!
a = 100; //Error! const宣告完的數值不可更改!!
}
console.log(a);//Error!!! 有block scope的特性,無法access回圈內宣告的變數!
```
----
Object constructor
```javascript=
// 實務上建構函數命名採單字首字大寫。狗狗物件有 name, age 屬性,方法是 wow
function Dog(name, age) {
// 屬性值
this.name = name;
this.age = age;
// 每個實例都會有一份方法副本
this.wow = function() {
console.log('wow!wow');
}
}
// 多個實例共用,可以減少記憶體等資源運用
Dog.prototype.cry = function() {
console.log('QQQ');
}
const dog = new Dog('lucky', 2);
// wow!wow!
dog.wow();
```
----
## 繼承
```javascript=
// 原型對象
var A = {
print: function () {
print('hello')
}
};
// 實例對象
var B = Object.create(A);
Object.getPrototypeOf(B) === A // true
B.print() // 印出hello
```
<!-- .slide: data-transition="slide" -->
----
### JSON (JavaScript Object Notation)
* object literal的子集
* XML可用來表現階層性資料,然而建立與處理XML DOM較為複雜,在Web應用程式中,許多時候並不需要用到XML的複雜階層性,此時通常會採用JSON作為資料交換格式。
<!-- .slide: data-transition="slide" -->
----
object
```javascript=
var obj = {
name : 'Justin',
age : 35,
childs : [ { name : 'hamimi', age : 3} ]
};
```
json
```javascript=
{
"name":"Justin",
"age":35,
"childs":[
{
"name":"hamimi",
"age":3
}
]
}
```
<!-- .slide: data-transition="slide" -->
----
* 以Node.js run server,以json格式傳http response
```javascript=
var http = require('http');
var server = http.createServer(function (req, res) {
if (req.url == '/') { //目標網址之port值後面的字串
res.writeHead(200, { 'Content-Type': 'application/json' });
res.write(JSON.stringify({ //stringify() method converts a JavaScript value to a JSON string
message: "Hello World",
name: "Aaron"
}));
res.end();
}
});
server.listen(5000);
console.log('Node.js web server at port 5000 is running..')
```
----
* [影片連結](https://youtu.be/ZNc2W8XnpIw)

<!-- .slide: data-transition="slide" -->
----

----
# Concurrency
<!-- .slide: data-transition="slide" -->
----
### 執行到完成(Run-to-completion)
當JS的一個函式開始執行時,他不會被取代且會在其他程式碼執行前先完成。這特性與 C 不同,在 C 當中,當一個函式在執行緒中執行時,隨時可以被其他執行緒中的程式碼中止。
<!-- .slide: data-transition="slide" -->
----
* Javascript為單執行緒語言
* 瀏覽器只分配給js一個主執行緒,用來執行函式,但一次只能執行一個函式
* 形成一個任務佇列排隊等候執行
* 某些任務耗時 (網路請求,定時器、事件監聽)
* 易導致網路頁面假死
* 瀏覽器為這些耗時任務開闢另外的執行緒(非同步)
<!-- .slide: data-transition="slide" -->
----

<!-- .slide: data-transition="slide" -->
----
### 以button實現interrupt (Mouse click in event queue)

<!-- .slide: data-transition="slide" -->
----
### 以button實現interrupt的code
```javascript=
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>SIMPLE DEMO</title>
<style>
* { padding: 0; margin: 0; }
canvas { background: #eee; display: block; margin: 0 auto; }
</style>
</head>
<body>
<canvas id="myCanvas" width="1000" height="480">
</canvas>
<button onclick="turn_dir()">turn</button>
<script>
// JavaScript code goes here
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var ballRadius = 10;
var x = canvas.width/2;
var y = canvas.height-30;
var xx = x+50;
var yy = y-50;
var dx = 2 ;
var dy = -2 ;
var dxx = 2 ;
var dyy = -2 ;
var score =0;
var g_dx=dx;
var g_dy=dy;
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.arc(xx, yy, ballRadius, 0, Math.PI*2);
ctx.fillStyle = "#DD00B0";
ctx.fill();
ctx.closePath();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
dx = -dx;
}
if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
dy = -dy;
}
if(xx + dxx > canvas.width-ballRadius || xx + dxx < ballRadius) {
dxx = -dxx;
}
if(yy + dyy > canvas.height-ballRadius || yy + dyy < ballRadius) {
dyy = -dyy;
}
x += dx;
y += dy;
xx += dxx;
yy += dyy;
}
setInterval(draw, 10);
function turn_dir() {
if(dx != 0 || dy != 0 ){ dx=0;dy=0;}
else{ dx = g_dx; dy=g_dy;}
}
</script>
</body>
</html>
```
----
### 單執行緒之函數互相切換
```javascript=
function f1(){ //函數1
console.log(11111);
setTimeout(function(){//切換函數
f2(); //呼叫函數2
},1000);//1秒
}
function f2(){//函數2
console.log(22222);
setTimeout(function(){//切換函數
f1(); //呼叫函數1
},1000);
}
f2(); //開始
```
<!-- .slide: data-transition="slide" -->
----

<!-- .slide: data-transition="slide" -->
----
#### 多個執行環境的互相溝通(Several Runtime communicating together)
Web worker 或是跨來源網域(cross-origin)的 iframe 都會有各自的堆疊、堆積及訊息佇列。兩個特定的執行環境只能透過 postMessage 這個方法來溝通。如果一個執行環境有監聽 message 事件時,另一個執行環境便可透過這個方法來新增一個訊息到該執行環境中。
<!-- .slide: data-transition="slide" -->
---
## 幾個熱門好用的Library, Framework
<!-- .slide: data-transition="slide" -->
----

<!-- .slide: data-transition="slide" -->
----
* Google開發並基於JavaScript的開源前端框架
* 主要實現單一頁面Web應用,不需要多次載入新的Url
* 資料雙向綁定上,非常易用且強大(Two Way Data-Binding)
* 適用於"CRUD"類型的Web應用程式
* Creation、Read、Update、Delete
* AngularJS規定如何實作這種操縱資料的程序,確保效能與易維護性
* 透過 宣告式語法 (Directives Syntax) 直接延伸現有的 HTML 架構
<!-- .slide: data-transition="slide" -->
----

<!-- .slide: data-transition="slide" -->
----

----

----
```htmlmixed=
<!DOCTYPE html>
<html ng-app> <!--宣告整份html都屬於AngularJS所管轄-->
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>
數量: <input type="number" ng-model="quantity" ng-init="quantity = 1"> <!--ng-model 屬性宣告成Model-->
<br>
單價: <input type="number" ng-model="price" ng-init="price = 299"> <!--ng-model 屬性宣告成Model-->
<br>
總價: {{ quantity * price }}
</body>
</html>
```
----

#### Lodash 能輕鬆操作陣列、物件、字串與數值,使用上也比較簡潔與直觀。
<!-- .slide: data-transition="slide" -->
----
### Array 操作
```javascript=
var X = require('lodash'); //載入lodash
X.chunk(['a', 'b', 'c', 'd'], 2); //array manipulation
//輸出[ [ 'a', 'b' ], [ 'c', 'd' ] ]
X.concat(['a', 'b', 'c', 'd'], ['e','f','g']);
//輸出[ 'a', 'b', 'c', 'd', 'e', 'f', 'g' ]
```
<!-- .slide: data-transition="slide" -->
----
### Object 操作
```javascript=
function Foo() {
this.a = 1;
}
function Bar() {
this.c = 3;
}
Foo.prototype.b = 2;
Bar.prototype.d = 4;
X.assignIn({'a':20},new Foo, new Bar);
//輸出{ a: 1, b: 2, c: 3, d: 4 }
```
<!-- .slide: data-transition="slide" -->
----
### String 操作
```javascript=
X.endsWith('abc', 'c');
//輸出true
X.capitalize('AARON');
//輸出Aaron
X.replace('Hello Fred', 'Fred', 'Aaron');
//輸出Hello Aaron
```
<!-- .slide: data-transition="slide" -->
----
### Collection
```javascript=
X.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
console.log(key);
console.log(value);
});
//輸出
//a 1 b 2
```
<!-- .slide: data-transition="slide" -->
----

----
## 先看看沒有jQuery的世界
```javascript=
var btn = document.querySelector('#btn'); //找標籤
btn.addEventListener('click', function() { //做binding
alert('click!');
});
```
<!-- .slide: data-transition="slide" -->
----
## 工程師都想偷懶一下
```javascript=
function getElement(elem) {
return document.querySelector(elem);
}
var btn = getElement('#btn'); //不用再寫那麼長
btn.addEventListener('click', function() {
alert('click!');
});
```
----
## 再偷懶一下
```javascript=
function getElement(elem) {
return document.querySelector(elem);
}
function addListener(elem, event, func) {
elem.addEventListener(event, func);
}
var btn = getElement('#btn');
addListener(btn, 'click', function() {
alert('click!');
});
```
----
## 極度乾燥(X)簡化(O)
```javascript=
function get(selector) {
var element = document.querySelector(selector);
return {
click: function(func) {
element.addEventListener('click', func);
}
}
}
get('#btn').click(function () {
alert('click!');
})
```
----

<!-- .slide: data-transition="slide" -->
----
### ~~自從去了巨匠.. 啊不是~~
### 自從有了jQuery
```javascript=
get('#btn').click(function () {
alert('click!');
})
```
將將
```javascript=
$('#btn').click(function () {
alert('click!');
})
```
<!-- .slide: data-transition="slide" -->
----

1. 程式碼簡潔
1. 類似CSS Selector的coding style, 程式碼接接樂
3. 可以大大提升開發的速度
4. ~~可以偷懶(喂~~
<!-- .slide: data-transition="slide" -->
---
# 實作
## 簡易聊天小糞Game
----
Project網址:
https://my-pl-project.herokuapp.com/

----
手機體驗的同學,建議使用google chrome並開啟電腦板模式

----
# 使用框架&套件:
Node.js + Heroku +Express + Socket.io + Phaser3
<!-- .slide: data-transition="slide" -->
----
# 輸入名稱

<!-- .slide: data-transition="slide" -->
----
### 連接至Server -> 加入聊天室

<!-- .slide: data-transition="slide" -->
----
# 尬廣跟上!!!

<!-- .slide: data-transition="slide" -->
----
## [DEMO影片](https://drive.google.com/file/d/1A_Ob5cA96lpMS46njylocjjW4WP7Xtft/view?usp=sharing)
---
# Reference
[參考資源1](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/A_re-introduction_to_JavaScript)
[var let const差別](https://medium.com/@totoroLiu/javascript-var-let-const-%E5%B7%AE%E7%95%B0-e3d930521230)
[wiki](https://zh.wikipedia.org/wiki/JavaScript)
[JavaScript 的歷史-陳鍾誠的網站](http://ccckmit.wikidot.com/js:history)
{"metaMigratedAt":"2023-06-15T00:10:56.501Z","metaMigratedFrom":"Content","title":"JavaScript","breaks":true,"contributors":"[{\"id\":\"229adf45-7604-4510-804a-af0769e67164\",\"add\":17964,\"del\":2383}]"}