# 學習基礎JS 如果網頁只有HTML跟CSS就感覺有些空虛,是時候要邁入網頁設計的下個階段 -- JavaScript,而畢竟是全新的語言,而且跟HTML、CSS不同,JS學起來較有脈絡,所以我決定從基礎開始記錄,重點如下 ## 變數 JS變數只有兩種宣告方式, const跟let (當然還有var,但好像漸漸被淘汰掉了),兩者就差在以後是否能修改,至於是哪種型態就看你怎麼初始化,跟Python有點像,基礎變數型態有數字、字串、布林...有些比較龐大的內容會拆開來講,這邊就簡單介紹 ```javascript= let age = "17"; //數字,JS無整數、浮點數之分 const name = "Weber"; //單雙引號無差別 const fat = true; age++; //age變18 name = "Weberorz"; //出錯,const不可修改 ``` 至於NULL跟undefined就輕鬆帶過 ## 自定義函式 JS的自定義函式語法也是跟C++大不相同,C\++需要在定義時決定return跟傳進來的變數型態,反之JS不必決定return的變數型態,傳進來的變數型態也是浮動的 ```javascript= const age = 17; const name = "Weber"; function WhatIsYourType(sth) { console.log(typeof(sth)); } WhatIsYourType(age); //輸出number WhatIsYourType(name); //輸出string ``` 新的ES6還能用簡化版的arrow function ```javascript= const age = 17; const name = "Weber"; const WhatIsYourType = (sth) => { console.log(typeof(sth)); } WhatIsYourType(age); //輸出number WhatIsYourType(name); //輸出string ``` ## 字串 字串有不少小東西可以講喔 ### 字串格式化 JS的字串格式化是我目前看過最精簡直覺的,只要把原本的引號換成‵ ‵然後在需要放變數的地方寫$\{變數\}就行了 ```javascript= const age = 17; const name = "Weber"; console.log(`Hi I'm ${name} and I'm ${age} years old`); //輸出Hi I'm Weber and I'm 17 years old ``` ### 字串合併 JS還能將不同的的資料型態合併成字串 ```javascript= const intro = "I'm Weber and I'm "; const age = 17; const anotherintro = " years old, yeah it's "; const A_boolean = true; const msg = intro + age + anotherintro + A_boolean; console.log(msg); //輸出I'm Weber and I'm 17 years old, yeah it's true ``` ### 內建的method JS內建很多方便的method,以下展示幾個應該還算常見的(至少是我目前看過的XD) ```javascript= const msg = "I really want to eat pizza"; console.log(msg.toUpperCase()); //轉大寫,輸出I REALLY WANT TO EAT PIZZA console.log(msg.toLowerCase()); //轉小寫,輸出i really want to eat pizza console.log(msg.length); //取得長度,輸出26 console.log(msg[14] + msg.charAt(15)); //兩種用index取得字元的方法,輸出to console.log(msg.substring(21, 26)); //取得子字串,輸出pizza const newMsg = msg.replace(/pizza/gi, "french fries"); //改變指定字,變成I really want to eat french fries console.log(newMsg); ``` 注意一下,這邊列出的method都不會改變字串原本的值 ## 條件判斷 JS的if else只有邏輯運算子比較特殊一點,==跟!=只會比較值,資料型態不同不計較,===跟!==則會連同資料型態一起嚴格比較 ```javascript= if (17 == "17") { console.log(`17 == "17"`); } //即使一個是數字、一個是字串,但對==沒差,回傳true,有輸出 if (17 != "17") { console.log(`17 != "17"`); } //同上,對!=來說他們倆相同,回傳false,無輸出 if (17 === "17") { console.log(`17 === "17`); } //因為資料型態不同,回傳false,無輸出 if(17 !== "17") { console.log(`17 !== "17"`); } //同上,對!==來說型態不同就回傳true,有輸出 ``` 也就是說,在JS裡,17 == "17"但17 !== "17" ## 陣列 JS陣列跟C++差異頗大,不只初始化不同,method也多很多 ### 初始化 我目前只看過這兩種初始化的方式 ```javascript= const foods = ["pizza", "fried rice", "pasta", "mash potato"]; //JS陣列能直接用中括號賦予值,還不用先宣告大小 const num = Array(5).fill(0); //跟C++的 int num[5]={} 一樣 ``` ### 各式method 超多~~~ ```javascript= console.log(foods[0]); //用index取得元素,輸出pizza console.log(foods.length); //取得長度=4 console.log(foods.indexOf("fried rice")); //取得index=1 foods.pop(); //移除尾端元素 foods.push("milk shake"); //將milk shake推入尾端 foods.shift(); //移除頂端元素 foods.unshift("apple pie"); //將apple pie 塞入頂端 foods.splice(3, 0, "strawberry"); //在位置3插入strawberry foods.splice(2, 1, "ramen", "choco cookie"); //移除位置2以後的一個元素,並在2的位置插入ramen 跟 choco cookie const AnotherFoods = foods.slice(); //複製陣列 //最後foods會變成['apple pie', 'fried rice', 'ramen', 'choco cookie', 'pasta', 'strawberry', 'milk shake'] ``` 話說splice好像能可以取代pop、push、shift、unshift,也太萬能XD ## 物件 這段偏向JS獨有,學起來就真的比較困難一點了 ### 物件的基本組成 有點像class喔,可以把不同資料型態打包起來 ```javascript= const about_me = { name: "Weber", age: 17, too_fat: true, hobby: ["coding", "sleep", "play badminton"] } console.log(about_me.hobby); //輸出['coding', 'sleep', 'play badminton'] ``` ### Method跟this 這邊就有點讓人頭痛了,特別是this,我就盡可能的解釋吧~ this在英文中是代名詞,在JS中其實也是,但"代替誰"就是重點啦,this預設是代替window object ```javascript= console.log(this); //輸出Window {window: Window, self: Window, document: document, name: '', location: Location, …}跟一堆函式 ``` 但把this放在object裡時,就代表那個object,也就是說,this的含意會跟著所在位置而浮動,並常用在object中的function(又稱method)中 ```javascript= const about_me = { name: "Weber", age: 17, too_fat: true, hobby: ["coding", "sleeping", "playing badminton"], intro: function() { console.log(`Hi I'm ${this.name} and I'm ${this.age} years old. I like ${this.hobby}`); } } about_me.intro(); //輸出Hi I'm Weber and I'm 17 years old. I like coding,sleeping,playing badminton ``` 這邊有個大大大重點,就是如果method用arrow function寫會怎樣 ```javascript= const about_me = { name: "Weber", age: 17, too_fat: true, hobby: ["coding", "sleeping", "playing badminton"], intro: () => { console.log(`Hi I'm ${this.name} and I'm ${this.age} years old. I like ${this.hobby}`); } } about_me.intro(); //輸出Hi I'm and I'm undefined years old. I like undefined ``` 欸,name怎麼變空字串,age跟hobby都變undefined,怎麼回事?! 這是因為ES6中,arrow function會被this給忽視,所以當this要去找object時會找不到,自然就變成undefined 那這樣設計用意何在?這就跟多層method有關了 ```javascript= const about_me = { name: "Weber", age: 17, too_fat: true, hobby: ["coding", "sleeping", "playing badminton"], intro: function() { console.log(`Hi I'm ${this.name} and I'm ${this.age} years old. I like ${this.hobby}`); function am_i_fat() { console.log(`you're fat, that's ${this.too_fat}`); } am_i_fat(); } } about_me.intro(); //輸出Hi I'm Weber and I'm 17 years old. I like coding,sleeping,playing badminton 跟 you're fat, that's undefined ``` 在這個例子中,am_i_fat中的this.too_fat變成undefined,因為am_i_fat是用function定義,this去找object時被攔下來,離真正的about_me還太遠,就變成undefined了,這種情況有兩種解法 第一種是定義一個that = this,使其不再浮動 ```javascript= const about_me = { name: "Weber", age: 17, too_fat: true, hobby: ["coding", "sleeping", "playing badminton"], intro: function() { console.log(`Hi I'm ${this.name} and I'm ${this.age} years old. I like ${this.hobby}`); const that = this; function am_i_fat() { console.log(`you're fat, that's ${that.too_fat}`); } am_i_fat(); } } about_me.intro(); //輸出Hi I'm Weber and I'm 17 years old. I like coding,sleeping,playing badminton 跟 you're fat, that's true ``` 但這樣寫有點弱弱的,所以arrow function被忽略的用處就誕生了 ```javascript= const about_me = { name: "Weber", age: 17, too_fat: true, hobby: ["coding", "sleeping", "playing badminton"], intro: function() { console.log(`Hi I'm ${this.name} and I'm ${this.age} years old. I like ${this.hobby}`); const am_i_fat = () => { console.log(`you're fat, that's ${this.too_fat}`); } am_i_fat(); } } about_me.intro(); //輸出Hi I'm Weber and I'm 17 years old. I like coding,sleeping,playing badminton 跟 you're fat, that's true ``` 所以,何時該用一般function定義,何時該用arrow function就是一門重要課題 好欸,大致上就這樣,object的水很深啦,但基礎就先這樣吧ヘ( ̄ω ̄ヘ) ## 迴圈 Object終於講完了,來講點輕鬆的迴圈好了 目前學了兩種迴圈,第一種跟C++非常像,定義一個變數來在範圍內跑 ```javascript= for(let i = 0; i < 10; ++i) { console.log(i); } //從1輸出到10 ``` 另一種則非常適合陣列,語法上有一點點類似C++的auto迭代器 ```javascript= const letters = [" ", "N", "e", "v", "r", "g", "o", "n", "a", "i", "y", "u", "p"]; const orders = [1, 2, 3, 2, 4, 0, 5, 6, 7, 7, 8, 0, 5, 9, 3, 2, 0, 10, 6, 11, 0, 11, 12]; let msg = ""; for(order of orders) { msg += letters[order]; } console.log(msg); //輸出Never gonna give you up ``` 迴圈挺簡單的喔耶~ ## Dom manipulation 終於到了最後一個觀念,而且終於要跟網頁互動了~這邊就直接拆成三個部分來講 ### Selctor Selector的功能就是選取網頁中的元素,有很多種寫法,我最常用的是querySelector系列 ```javascript= const topic = document.querySelector(".topic"); //用CSS語法即可選取,若有同類型只抓第一個 const content = document.querySelectorAll("p"); //抓多個元素用 ``` 當然還有getElementsByClassName跟getElementsById,只是就真的比較少用 ### Style 基本上就是在JS裡寫CSS ```javascript= const topic = document.querySelector("h1"); topic.style.color = "red"; ``` 標題就會從白色 ![](https://i.imgur.com/nhUYDIs.png) 變紅色 ![](https://i.imgur.com/jTIjgg6.png) 有夠醜,真正設計千萬別這樣搞XD ### addEventListener 壓軸的addEventListener就是偵測網頁活動的功能 #### click ```javascript= const topic = document.querySelector("h1"); topic.addEventListener("click", () => { topic.style.color = "red"; console.log("Your topic has bocome red"); }) ``` 效果如下 ![](https://i.imgur.com/m1WbJfx.gif) #### scroll scroll的思路跟click比較不同,即使我們想要標題改變顏色,但被捲動的其實是document,不是h1,所以scroll要去抓"被捲動的容器" ```javascript= const topic = document.querySelector("h1"); document.addEventListener("scroll", () => { topic.style.color = "red"; console.log("Your topic has bocome red"); }) ``` 效果長這樣 ![](https://i.imgur.com/RGFM5Ef.gif) 可以看到,在捲動的同時,console也瘋狂輸出 ### querySelectorAll注意事項 這邊還有一個需要注意的小重點喔,querySelectorAll選出來的多個元素會被抓到一個NodeList裡,直接寫addEventListener跟style會出錯,需要開一個迴圈跑,一一下指令 ```javascript= const content = document.querySelectorAll("p"); for(contentChild of content) { contentChild.addEventListener("click", () => { console.log("red content"); }) } ``` 變這樣 ![](https://i.imgur.com/6WfTooO.gif) ## 小小的結語 好累喔,一個不小心打到快兩點Σ(っ °Д °;)っ 東西有點多,學跟整理的時候都有點累,但感覺挺值得的,下個主題就是JS網頁實戰啦~ --- <ul style ="display: flex; flex-direction: row; width: 100%; justify-content: space-between;margin: 0; padding: 0;"> <li style="list-style: none;"><a href = "https://hackmd.io/@WeberChang/BJ6op5i0t" >上一篇</a></li> <li style="list-style: none;"><a href = "https://hackmd.io/@WeberChang/rJBpwRsut">主頁</a></li> <li style="list-style: none;"><a href = "https://hackmd.io/@WeberChang/HJsIMGYFF">下一篇</a></li> </ul>