# 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 語言創始人 ![Brendan Eich](https://i.imgur.com/6uZDXIJ.jpg) * 公司要求做出掛載在瀏覽器上的小工具 <!-- ## 開發動機? --> <!-- * 作為瀏覽器內置的腳本語言,為網頁開發者提供操控瀏覽器的能力,目前為唯一所有瀏覽器通用的腳本語言,幾乎全世界的網頁都使用Javascript。 --> ---- ![NetScape](https://i.imgur.com/LWj6gNN.png) ![Sun](https://i.imgur.com/oR6Uop2.png =700x150) ---- ![IE3](https://i.imgur.com/hRMLulV.png) ### JavaScript推出不久後 ### 微軟公司為Internet Explorer 3瀏覽器推出了JScript ---- ![ECMA](https://i.imgur.com/dWRBpLs.png =700x150) ### 歐洲電腦製造商協會(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 在網頁到底佔了什麼角色? ---- ![](https://i.imgur.com/dIGttyi.png) <!-- .slide: data-transition="slide" --> ---- ## 操作方法 ## 瀏覽器環境提供 * BOM * DOM ---- ## BOM? BOM (Browser Object Model,瀏覽器物件模型) 提供JavaScript與瀏覽器互動的API * 開啟/關閉視窗 * 改變視窗大小 * 計時器與取得網址..等 ---- ## 架構圖 ![](https://i.imgur.com/7VrDAGW.png) ---- ## 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" --> ![](https://i.imgur.com/StOJawP.png) ---- ## 一個將 HTML 文件以樹狀的結構來表示的模型 <!-- .slide: data-transition="slide" --> ---- ```htmlembedded= <html> <head> <title>一個簡單的網頁</title> </head> <body> <h1>這是標題</h1> <p>這是一個<i>簡單</i>的網頁</p> </body> </html> ``` <!-- .slide: data-transition="slide" --> ---- ![](https://i.imgur.com/cbDNcNP.png =1000x) ---- ## 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) ![](https://i.imgur.com/nvCFvsP.gif) <!-- .slide: data-transition="slide" --> ---- ![](https://i.imgur.com/YKUsTId.png =600x) ---- # Concurrency <!-- .slide: data-transition="slide" --> ---- ### 執行到完成(Run-to-completion) 當JS的一個函式開始執行時,他不會被取代且會在其他程式碼執行前先完成。這特性與 C 不同,在 C 當中,當一個函式在執行緒中執行時,隨時可以被其他執行緒中的程式碼中止。 <!-- .slide: data-transition="slide" --> ---- * Javascript為單執行緒語言 * 瀏覽器只分配給js一個主執行緒,用來執行函式,但一次只能執行一個函式 * 形成一個任務佇列排隊等候執行 * 某些任務耗時 (網路請求,定時器、事件監聽) * 易導致網路頁面假死 * 瀏覽器為這些耗時任務開闢另外的執行緒(非同步) <!-- .slide: data-transition="slide" --> ---- ![](https://i.imgur.com/x6QtcrL.jpg =800x) <!-- .slide: data-transition="slide" --> ---- ### 以button實現interrupt (Mouse click in event queue) ![balls](https://i.imgur.com/yWcp9kY.gif) <!-- .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" --> ---- ![test.js](https://i.imgur.com/lnPSQTX.gif) <!-- .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" --> ---- ![](https://i.imgur.com/KIkwsxg.png) <!-- .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" --> ---- ![](https://i.imgur.com/G7EMUzc.png =800x) <!-- .slide: data-transition="slide" --> ---- ![](https://i.imgur.com/ct1KLFD.png) ---- ![](https://i.imgur.com/rNjAWXc.gif =800x) ---- ```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](https://i.imgur.com/JUYHGLW.png) #### 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" --> ---- ![](https://i.imgur.com/BAluSOT.png) ---- ## 先看看沒有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!'); }) ``` ---- ![](https://i.imgur.com/f2aJRbK.png) <!-- .slide: data-transition="slide" --> ---- ### ~~自從去了巨匠.. 啊不是~~ ### 自從有了jQuery ```javascript= get('#btn').click(function () { alert('click!'); }) ``` 將將 ```javascript= $('#btn').click(function () { alert('click!'); }) ``` <!-- .slide: data-transition="slide" --> ---- ![](https://i.imgur.com/BAluSOT.png) 1. 程式碼簡潔 1. 類似CSS Selector的coding style, 程式碼接接樂 3. 可以大大提升開發的速度 4. ~~可以偷懶(喂~~ <!-- .slide: data-transition="slide" --> --- # 實作 ## 簡易聊天小糞Game ---- Project網址: https://my-pl-project.herokuapp.com/ ![](https://i.imgur.com/37thgri.png =500x) ---- 手機體驗的同學,建議使用google chrome並開啟電腦板模式 ![](https://i.imgur.com/mw7F1Jz.jpg =300x) ---- # 使用框架&套件: Node.js + Heroku +Express + Socket.io + Phaser3 <!-- .slide: data-transition="slide" --> ---- # 輸入名稱 ![](https://i.imgur.com/Lfs22HC.png) <!-- .slide: data-transition="slide" --> ---- ### 連接至Server -> 加入聊天室 ![](https://i.imgur.com/spTAT9K.jpg) <!-- .slide: data-transition="slide" --> ---- # 尬廣跟上!!! ![](https://i.imgur.com/CSi8SQb.jpg) <!-- .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}]"}
    201 views