關於 JavaScript

關於 JavaScript

JavaScript 常用功能

JS 基礎使用?

獲得文本
<body>
<input type="text" id="input" />
 <p id="element"></p>    
 <button onclick="getOnScreen()">獲得元素</button>
</body>
<script>
function getOnScreen(){ //獲得元素
    const inputElement = document.getElementById('input');
    let inputValue = inputElement.value;
    alert(inputValue) 
}
</script>
獲得表單(select)
<body>
 <div>
  <form name="form_name" id="form_name">
    <select name="country">
      <option value="台灣">台灣</option>
      <option value="韓國">韓國</option>
      <option value="日本">日本</option>
    </select>
    <button onclick="getCountry()"> 取得 Select</button>
  </form>
 </div>
</body>
<script>
function getCountry(e) {
  e = e || event;
  e.preventDefault();
  const form = document.getElementById("form_name");
  let country = form.country.value;
  alert(country);
}
</script>
獲得表單(radio)
<body>
 <div>
  <form name="form_name" id="form_name">
    <label><input name="language"type="radio" value="繁中" checked/>繁中</label>
    <label><input name="language" type="radio" value="韓文" />韓文</label>
    <label><input name="language" type="radio" value="日文" />日文</label>
    <br />
    <button onclick="getLanguage()">取得 Radio</button>
  </form>
 </div>
</body>
<script>
function getLanguage(e) {
  e = e || event;
  e.preventDefault();
  const form = document.getElementById("form_name");
  for (let i=0;i<form.language.length;i++){
      if(form.language[i].checked){
          let language = form.language[i].value
          alert(language);
      }
  }
}
</script>
插入文本(插入到元素內)
<body>
 <input type="text" id="input" />
 <p id="element"></p>    
 <button onclick="writeOnScreen()">寫入元素</button>
</body>
<script>
function writeOnScreen(){ //寫入元素
    const inputElement = document.getElementById('input');
    const writeElement = document.getElementById('element')
    let inputValue = inputElement.value;
    writeElement.innerHTML = inputValue
}
</script>
插入文本(插入到 input)
<body>
 <input type="text" id="inputOne" />
 <input type="text" id="inputTwo" />
 <button onclick="writeOnInput()">寫入 input</button>
</body>
<script>
function writeOnInput() {
  //寫入 input
  const inputOne = document.getElementById("inputOne");
  const inputTwo = document.getElementById("inputTwo");
  inputTwo.value = inputOne.value
}
</script>
循環 輸出陣列值
<body>
 <button onclick="checked()">輸出陣列值</button>
 <p id="element"></p>
</body>
<script>
function checked() {
  let num = [];
  let element = document.getElementById("element");
  for (let i = 0; i < 10; i++) {
     num.push(i);
  }
  element.innerHTML = num
}
</script>

JS 進階使用?

showIdInput()

showIdInput    (ID)顯示 input 的數值  showIdInput('input Id','element Id') 
writeElement    (ID)寫入 element 的數值  writeIdElement('element Id','value')


<button onclick="showIdInput('input','element')">按鈕</button>
<input type="text" id="input" value="123" />
<p id="element"></p>

//顯示 input(ID) 的數值
function showIdInput(input,el) {
   const inputElement = document.getElementById(input);
   let inputValue = inputElement.value;
   writeIdElement(el,inputValue);
};
//寫入 element(ID) 的數值
function writeIdElement(el,val){
   const writeElement = document.getElementById(el);
   writeElement.innerHTML = val;
}

getAtoBInput()

getAtoBInput (ID)取得 A Input 到 B input  getAtoBInput('element Id','element Id')


<button onclick="getAtoBIdInput('a','b')">確認登入狀況</button>
<input type="text" id="a" />
<input type="text" id="b">

//(ID)取得 A Input 到 B input
function getAtoBIdInput(id_1, id_2) {
  const inputOne = document.getElementById(id_1);
  const inputTwo = document.getElementById(id_2);
  inputTwo.value = inputOne.value;
}

showIdSelect()

showIdSelect('form Id','element Id')


//(ID)顯示 select 的值 
// 小 Bug 需要修正(必須要修改 formName.xxx.value )
// xxx 為 select 的 name

<div>
  <form name="form_name" id="form_name">
    <select name="country">
      <option value="m">男生</option>
      <option value="w">女生</option>
    </select>
    <br />
    <button onclick="showIdSelect('form_name','element')">
      確認登入狀況
    </button>
  </form>
</div>
<p id="element"></p>

function showIdSelect(form, el, e) {
  e = e || event;
  e.preventDefault();
  const formName = document.getElementById(form);
  let value = formName.country.value;
  writeIdElement(el,value)
}

參考資料

  1. [筆記] 透過javascript擷取HTML元素(讀取radio, select, id 的值)

  2. JS 取消默認事件行為

JS 內建函數使用?

  • split 分割字串
  • filter 過濾陣列
    • 數值陣列過濾
    • 字串陣列過濾
  • indexOf 索引位置
    • 字串比較
    • 陣列比較
  • join 合併一個陣列為一個字串

split 方法使用指定的分割字串符將 String 對象分割成字串陣列,以分割字符串分割確定好每個分割的位置

split(String,"")    //回傳字串 S,t,r,i,n,g
split(String," ")   //回傳字串 String
<body>
 <p id="element"></p>
</body>
<script>
let splitStr = 'The quick brown fox jumps over the lazy dog';
splitString(splitStr," ");
function splitString(splitStr, separator) {
  const writeElement = document.getElementById("element");
  writeElement.innerHTML = splitStr.split(separator);
}
</script>
<!-- 結果 -->
<p id="element">The,quick,brown,fox,jumps,over,the,lazy,dog</p>
Tips
如果空字串("")被用作分隔符號,則字串會在每個字符之間分割

filter 創建一個新陣列,其包含通過所有函數實現的測試所有元素

//數值陣列過濾
<body>
 <p id="element"></p>
</body>
<script>
let filterNumber = [12, 5, 8, 130, 44];
let showFilterItme = filterNumberArray(filterNumber);
function filterNumberArray(filterItem) {
  //數值陣列過濾
  function isBigEnough(element) {
    //排除較小的數值
    return element >= 10;
  }
  return filterItem.filter(isBigEnough);
}
document.getElementById("element").innerHTML = showFilterItme;
</script>
<!-- 結果 -->
<p id="element">12,130,44</p>

<!-- filter 的另一種寫法 
將 isBigEnough 函數改用 匿名函數寫在 filter 內-->
function filterNumberArray(filterItem) {
  return filterItem.filter(function(el) {
    return el >= 10;
  });
}
//文字陣列過濾
<body>
 <p id="element"></p>
</body>
<script>
let filterString = ["Apple", "Banana", "Grapes", "Mango", "Orange"];
let showFilterItme = filterStringArray("ap");
function filterStringArray(filterItem) {
  return filterString.filter(function(el){
    return el.toLowerCase().indexOf(filterItem.toLowerCase()) > -1;
  });
}
document.getElementById("element").innerHTML = showFilterItme;
</script>

<!-- 結果 
輸入 filterArray("ap") 所得到的結果-->
<p id="element">Apple,Grapes</p>

indexOf 返回調用它的 String 對象中第一次出現的指定值的索引,從 fromIndex 處進行搜索。如果未找到該值,則返回 -1。

//字串比較
//字串陣列中找第一次出現位置
<body>
 <p id="element"></p>
</body>
<script>
let str = 'To be, or not to be, that is the question.';
let show = str.indexOf('n');
document.getElementById("element").innerHTML = show;
</script>
<!-- 結果 -->
<p id="element">10</p>
  • 左側.indexOf(右側) 左側為對照,右側拿來跟左側比較
  • fromIndex 從1開始計算,空白也包含索引計算
//陣列比較
<body>
 <p id="element"></p>
</body>
<script>
let str = "This website is for losers LOL";
let show = disemvowel(str);
function disemvowel(str) {
  let vowels = ["a", "e", "i", "o", "u"];
  return str
    .split("")
    .filter(function(el) {
      return vowels.indexOf(el.toLowerCase()) == -1;
    })
    .join("");
}
document.getElementById("element").innerHTML = show;
</script>

<!-- 結果 -->
<p id="element">Ths wbst s fr lsrs LL</p>

join 將一個陣列(或一個陣列對象)的所有元素連成一個字串並返回這個字串

<body>
 <p id="element"></p>
</body>
<script>
let joinStr =['Wind', 'Rain', 'Fire']
let showJoinString = joinStr.join('');
document.getElementById("element").innerHTML = showJoinString;
</script>
<!-- 結果 -->
<p id="element">Wind,Rain,Fire</p>

joinStr.join();      //值為 "Wind,Rain,Fire"
joinStr.join(', ');  //值為 "Wind, Rain, Fire"
joinStr.join(' + '); //值為 "Wind + Rain + Fire"
joinStr.join('');    //值為 "WindRainFire"

JS 實戰功能?

簡易的登入狀態
<div>
  <form name="form_name" id="form_name">
    <h2>登入者身分</h2>
    <select name="login">
      <option value="Employee">登入</option>
      <option value="Director">登入中</option>
      <option value="Cancel">尚未登入</option>
    </select>
    <button onclick="loginCheck()">確認登入狀況</button>
  </form>
</div>
<p id="element"></p>
function loginCheck(e) {
  e = e || event;
  e.preventDefault();
  let form = document.getElementById("form_name");
  let element = document.getElementById("element");
  let login = form.login.value;
  let message;
  let result =
    login == "Employee"
      ? "Hello"
      : login == "Director"
      ? "Greetings"
      : login == ""
      ? (message = "請重新登入")
      : "";
  element.innerHTML = result;
}
簡易的登入確認
<button onclick="loginCheck()">確認登入狀況</button>
<p id="element"></p>

function loginCheck() {
  let username = prompt("你是誰?", "");
  let message = document.getElementById("element");
  if (username == "Admin") {
    let password = prompt("請輸入密碼", "");
    if (password == "TheMaster") {
      message.innerHTML = "歡迎您回來!";
    } else if (password == "" || password == null) {
      message.innerHTML = "請填寫正確資料";
    } else {
      message.innerHTML = "您的密碼輸入錯誤";
    }
  } else if (username == "" || username == null) {
    message.innerHTML = "請填寫正確資料";
  } else {
    message.innerHTML = "我不知道你是誰?" }


JavaScript 筆記

關於使用 use strict

"use strict" 嚴格模式寫在 JS腳本前面,此段指令將瀏覽器引擎轉為"現代"模式,改變一些內建特性的行為。

一些新語言特性諸如 "classes" 和 "modules" 也會自動開啟嚴格模式。

變量與常量?

let 變量,定義值之後,可變動值
const 常量,定義值之後,不可變動值

正確命名變量?

變量命名是編程過程中最重要和最複雜的技能之一。快速地瀏覽變數的命名就知道代碼是一個初學者還是有經驗的開發者書寫。

在一個現實項目中,大多數的時間用來修改和擴充現有的代碼庫,而不是從頭開始寫一些完全獨立的代碼。當一段時間後,我們做其他事情,重返我們的代碼,找到命名的信息要容易的多。換句話說,變量要有個好名字。

  • 使用人類可讀的命名
  • 變量名要能夠精準描述變量並且足夠簡潔,如果能夠非常明顯從上下文知道數據所表達的含意,這樣使用它們也是可以的。

重用還是新建?

最重要的一點,有些懶惰的程序員,傾向於重用現有的變量,而不是聲明一個新的變量。

結果是,這個變量就像是被仍進不同東西的箱子,而沒有改變它的貼紙。現在裡面是什麼? 誰知道呢。我們需要靠近一點,然後檢查它。

這樣的程序員節省了一點變量聲明的時間,但卻在調適代碼的時候損失數十倍時間。

目前的JavaScript 壓縮器和瀏覽器都很夠很好地優化代碼,所以不會產生性能問題。為不同的值使用不同的變量可以幫助引擎進行優化。

JavaScript 有七種基本的數據類型?

  • number 用於任何類型的數字:整數或者浮點數
  • string 用於字串。
  • boolean 用於 true 和 false
  • null 用於未知的值
  • undefined 用於為定義的值
  • object 用於複雜的數據結構
  • symbol 用於生成一個全局唯一的值

typeof 運算符可以查看變量的類型

let x = "文字";
typeof x; //string

null 返回 "object",這是語言中的錯誤,實際上它並不是一個對象

實作: createRace 以JS簡易的透過選單並按下按鈕後,得到相對應的資料。

類型轉換?

大多情況下,運算符號和函數會自動轉換為正確的類型,如果為確保輸出示正確的類型可以使用以下函數

ToString 當需要一個值為字符串形式,就會進行 string 類型轉換

let value = 123
alert(typeof value)         //number
alert(typeof String(value)) //string

ToNumber 在算數函數和表達式中,會自動進行 number 類型轉換

let str = "123";
alert(typeof str); //string
let num = Number(str);
alert(typeof num); //number

Number 類型轉換規則
輸入                輸出
undefined       NaN
null                 0
true 和 false    1 nad 0
string              如果去掉首尾空格後的純數字字符串中包含的數字。如果去掉首尾空格後的字符串僅包含空格字符組成,返回0。如果字符串不是純數字,則返回NaN。

alert( Number("   123   ") ); // 123
alert( Number("123z") );      // NaN (error reading a number at "z")
alert( Number(true) );        // 1
alert( Number(false) );       // 0

ToBoolean 轉換為 boolean 類型是為最簡單的一個

假值,某種0,空的串聯,null,undefined和NaN變成false。
其他值變成true。

alert( Boolean(1) ); // true
alert( Boolean(0) ); // false

alert( Boolean("hello") ); // true
alert( Boolean("") ); // false

運算符?

術語:一元運算符、二元運算符、運算元

運算元 5 * 2,有兩個運算元,左運算元 5,右運算元 2
一元運算符 一個運算符只有一個運算元,那麼就是一元運算符

let x = 1;
x = -x;  
alert(x); -1,一元負號運算符生效

字符串連接功能,二元運算符 +

alert('1' + 2 ); // "12"
alert( 2 + '1'); // "21"

只要任一運算元是字串,那麼其他運算元也將轉化為字符串
可以看出,不管字符串是在前和在後都不會影響這個規則

alert( 2 + 2 + '1'); // "41" 而不是 "221"

字符串連接和轉化是二元運算符 + 的一個特性。其他的數學運算符都只對數字有效。通常,他們會轉化運算元為數字

alert( 2 - '1' );   //1
alert( '6' / '2' ); //3

數字轉化功能,一元運算符 +

// 對數字無效
let x = 1;
alert( +x ); // 1

let y = -2;
alert( +y ); // -2

運算符優先級?

我們都知道表達式 1 + 2 * 2 中,乘號優先於加法計算,這個就是優先級的問題。 
乘法比加法擁有更高的優先級。

優先級    名稱        符號
16          一元加號    +    
16          一元負號     -        
14          乘號            *
14          除號            /
13          加號            +
13          減號            -
3            賦值符         =  

賦值運算符號

= 也是一個運算符

鏈式賦值由右到左執行

let a, b, c;

a = b = c = 2 + 2;

alert( a ); // 4
alert( b ); // 4
alert( c ); // 4

求餘式運算符 %

運算符 % 儘管看上去是個百分號,但和百分號沒有甚麼關係。
a % b 的結果是 a 除以 b 的餘數

alert( 5 % 2 ); // 1 
alert( 8 % 3 ); // 2
alert( 6 % 3 ); // 0

冪運算符 **

對於自然數 b, a ** b 的結果是 a 與自己相乘 b 次方

alert( 2 ** 2 ); // 4 (2*2)
alert( 2 ** 3 ); // 8 (2*2*2)
alert( 2 ** 4 ); // 16(2*2*2*2)

這個運算符對於 a 和 b 是非整數的情況依然適用

alert( 4 ** (1/2) ); // 2 (1 / 2 冪運相當於開方 √,這是數學常識)
alert( 8 ** (1/3) ); // 2 (1 / 3 冪運相當於開三次方 )

 

自相加/自相減

對一個數進行加一、減一是最常見的數值運算符

let counter = 2;
counter++; //3
counter--; //2

運算符 ++ 和 -- 可以放置在變量前或者變量後。

  • 當運算符在變量後,被稱為後置形式: counter++
  • 當運算符在變量前,被稱為前置形式: ++counter

兩者都是做同一件是,將變量 counter 與 1 相加。
所以總結是:

如果我們想要對變量自相加並且立即使用值,那麼我們需要使用前置形式
let counter = 0;
alert( ++counter ); //1
如果我們想要使用之前的值,那麼我們需要使用後置形式
let counter = 0;
alert( counter++ ); //0
Tips
++/-- 運算符的優先級比絕大部分的運算符還要高
let counter = 1;
alert( 2 * ++counter ); //4

位運算符

a & b  // AND
a | b  // OR

修改並替換

我們經常需要對一個變量進行操作,然後把新的結果儲存給變量。

let n = 2;
n += 5 // now n = 7(同 n = n + 5)
n *= 2 // now n = 14(同 n = n * 2)

逗號運算符

有時候它用來寫更簡短的代碼,因此為了能夠了解代碼,我們需要了解它。
逗號運算符能讓我們處理更多語句,使用 , 將他們分開。每個語句都會運行,但是只有最後的語句結果會被返回

let a = (1+2, 3+4);
alert( a ); //7 (3+4 的結果)

這裡,第一個語句1 + 2運行了,但是它的結果被替換了,然後3 + 4運行,計算結果被返回。

值的比較

常用的數學符號進行值得比較:

  • 大於/小於: a>b , a<b 
  • 大於等於/小於等於: a>=b , a<=b
  • 檢測兩個值得相等: a == b (如果單寫一個 a = b 則表示賦值)
  • 檢測兩個值得不等於: a!=b

比較結果為 Boolean 類型
和其他操作符一樣,比較操作符號也會有返回值,其類型為布林值 Boolean

  • true 表示 "yes"(是),"correct"(正確),或"the truth"(真理)
  • false 表示 "no"(否),"wrong"(錯誤),或"not the truth"(非真理)
alert(2 > 1); //true
alert(2 == 1); //false
alert(2 != 1); //true

字符串間的比較

字符串是按字符(母)逐個進行比較的

alert('Z'>'A'); //true

字符串間的比較算法非常簡單:

  • 首先比較兩個字符串的首位字符大小。
  • 如果一方字符較大(或較小),則該字符串大於(或小於)另一個字符串。算法結束。
  • 否則,兩個字符串中的字符相等,繼續取出各自的後一位字符進行比較。
  • 重複上述步驟進行比較,直到某字符串率先用完所有字符。
  • 如果兩個字符串同時用完字符,那麼它們被判定為相等,否則未結束(還有未比較的字符)的字符串更大。
Tips
非真正的字母順序,而是 Unicode 編碼順序。
比如說 大寫的 A 與小寫的 a 比較,a > A 為 true,這是因為 JavaScript 使用內建的編碼表中 Unicode 小寫字母的字符索引更大。

不同類型的比較

當不同類型的值進行比較時,它們首先被轉為數字 number 再判斷大小

alert( '2' > 1 ); //true,字符串 '2',會被轉為數字 2
alert( '01' == 1);//true,字符串 '01',會被轉為數字 1

對於布爾類型,true會被轉為1,false轉為0

alert( true == 1); //true
alert( false == 0); //true

對於JavaScript而言這種現象蠻正常的,因為它會把待比較的值轉為數字後再做比較(因此“ 0”變成了0)。若只是將一個變量轉為Boolean,則使用其他的類型轉換規則。

let b = "0";
alert( Boolean(b) ); // true

嚴格相等

普通的相等性檢查 == 存在一個問題,它不能分出 0 和 false。
所以需要以 === 嚴格相等操作符來進行相等性檢查

alert( 0 === false); //false,比較不同類型的值

同樣的,與"不相等"符號 != 類似,"嚴格不相等"表示 !==

涉及 null 和 undefined 的比較

alert( null === undefined); //false,因為他們屬於不同的類型
alert( null == undefined);  //true,JavaScript 存在的一個專屬的規則,會判斷它們互等
Tips
當使用數學式或其他比較方法<> <=> =時:
null / undefined的值會被轉換為數字:
null 轉為0,undefined轉為NaN
alert( null > 0 );  // (1) false,(0>0 false)
alert( null == 0 ); // (2) false,null 與 0 兩者類型不同(null == number fasle)
alert( null >= 0 ); // (3) true,null 轉為 0(0=0 true)

進行值的比較會把null轉為數字,因此它被轉換為了0。這就是為什麼(3)中null> = 0返回true,(1)中null> 0返回false。

同時,undefined和null在預定性檢測==中不會進行任何的類型轉換,它們有自己獨立的比較規則,所以另外它們之間互等外不會等於任何其他的值。由此解釋了為什麼(2)中null == 0會返回false。

拒不合作”的 undefined

alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)

(1)和(2)中返回false是因為undefined在比較中被轉換為了NaN,而NaN是一個特殊的數值型取值,它與任何值進行比較都會返回false。
(3)中返回false是因為這是一個替代性檢測,而undefined只與null近似,不會與其他值替代。

規避錯誤

除非你非常清楚自己在做什麼,否則永遠不要使用> => <<=去比較一個可能為null / undefined的變量。對於取值可能是null / undefined的變量,請按需要分別檢查它的取值情況。

小總結

  • 比較操作符始終返回邏輯值。
  • 字符串間按“詞典”順序逐字符比較大小。
  • 當待比較的值類型不同時,它們會被轉為數字(不包括嚴格相等檢測)進行比較。
  • 在非嚴格定義==下,null和undefined一致且各自不等於任何其他的值。
  • 在使用>或<進行比較時,需要注意變量可能為null / undefined的情況。比較好的方法是單獨檢查變量是否等於null / undefined。

三種瀏覽器顯示訊息的方式

alert 瀏覽器會跳出一段訊息並暫停腳本,直到用戶點擊了"確定"

alert("Hello");

prompt 瀏覽器會顯示一個帶有文本消息的動態窗口,還有 input 框和確定/取消按鈕。

prompt 函數接收兩個參數  

result = prompt(title[, default]);
  • title 顯示給用戶的文本
  • default 可選擇第二個參數,指定 input 框的初始值

用戶在prompt對話框的input框輸入文本並點擊確定。不然就點擊取消按鈕或敲擊Esc鍵來取消。
prompt返回輸入的文本;如果取消輸入就返回null。
 

//使用對話框做回應判斷

prompt 
let value = prompt("請輸入數字", "");
if (value < 0) {
  alert(-1);
}else if(value > 0){
  alert(1)
}else{
  alert(0)
}

confirm

result = confirm(question);

確認函數顯示一個帶有問題和兩個按鈕的模態窗口:確定和取消。

點擊確定返回true,點擊取消返回false。

let isBoss = confirm("Are you the boss?");

alert( isBoss ); // true 如果“確定”被按下

條件運算符 if

  • if 假設語句
  • else 假設語句不成立,執行 else if
  • else if 多個條件

三則運算符 '?'

有時我們需要根據一個條件去賦值一個變量

let assessAllowed;
let messageOne = "您已滿 18 歲,可進入";
let messageTwo = "您未滿 18 歲,不可進入";
let age = prompt("您現在年齡是?", "");
let result =
  age > 18 ? (assessAllowed = messageOne) : (assessAllowed = messageTwo);
alert(assessAllowed);
Tips
技術上,我們可以省略 age > 18 外面的括號。因為問號運算符的優先級較低,所以它在 > 後面執行

多個 '?'

使用一系列問號運算符可以返回一個取餘多個條件的值

let age = prompt("age?", "");
let message =
  age < 3
    ? "Hi baby!"
    : age < 18
    ? "Hello!"
    : age < 100
    ? "Greetings"
    : "What an unsual age!";
alert(message);

邏輯運算符

javaScript 裡有三個邏輯運算符: ||(或)、&&(與)、!(非)

|| (或 OR)

result = a || b;

alert( true  || true );  // true
alert( false || true );  // true
alert( true  || false ); // true
alert( false || false ); // false

result = value1 || value2 || value3;

或運算符||做了如下的事情:

  • 從左到右依次計算操作數。
  • 如果結果是true,就停止計算,返回這個操作數的初始值。
  • 如果所有的操作數都被計算過(也就是,轉換結果都是false),返回最後一個操作數。

&& (與 AND)

result = a && b;

alert( true  && true );  // true
alert( false && true );  // false
alert( true  && false ); // false
alert( false && false ); // false

與運算&&做了如下事情:

  • 從左到右依次計算操作數。
  • 如果結果是false,就停止計算,返回這個操作數的初始值。
  • 如果所有的操作數都被計算過(也就是,轉換結果都是true),返回最後一個操作數。
Tips
&& 運算符 在 || 運算符之前執行
所以代碼 a && b || c && d 與 && 表達式加了括號一樣 (a && b) || (c && d)
let x = 1;
(x > 0) && alert( 'Greater than zero!' );

&&右邊的代碼只有運算到達到此處才能被執行。也就是,當且僅當(x> 0)返回了真值。

! (非 NOT)

result = !value;

alert( !true ); // false
alert( !0 ); // true

while 當..循環 

let i=0;
while(i<3){
 alert(i);
 i++;
}

如果上面的程式碼沒有i++ 的話,那麼循環會永遠重複
任何表達式或變量都可以是循環條件,而不僅僅是比較。對它們進行計算,並通過 while 將其結果轉化為布林值

例如: while(i != 0) 可簡寫成 while(i)

let i = 3;
while (i) { //當 i 變成 0 時,條件為 false 循環結束
  alert(i);
  i--;
}

do...while

循環首先執行一次程式後,再檢查條件是否為真,是的話重複執行循環

let i = 0;
do{
  alert(i);
  i++;
}while(i<3)

這種形式的語法很少使用,通常以其他形式為首選 while(...){...}

for 循環

// for(let i = 0; i <3; i ++)alert(i)

//開始
let = 0

if(i <3){alert(i); i ++} //如果條件為真,運行下一步
if(i <3){alert(i); i ++} //如果條件為真,運行下一步
if(i <3){alert(i); i ++} //如果條件為真,運行下一步

// ...結束,因為現在i == 3

跳出循環

通常條件為假時,停止循環

break 強制退出這個循環

let sum = 0;
while (true) {
  let value = +prompt("Enter a number", "");
  if (!value) break; // (*)
  sum += value;
}
alert("Sum: " + sum);

如果用戶輸入空行或取消輸入,在(*)行break指令會被激活。它立即終止循環,將控制權傳遞給循環後的第一行,即,alert。

根據需要,“無限循環+ break”的組合非常適用於不必在循環開始/結束時檢查條件,但在中間甚至是各自的多個位置進行檢查的情況。

繼續下一個跌代

continue 指令是 break 的"輕量版"。這並不會阻止整個循環,相反地,它將停止當前的跌代,並強制啟動新一輪循環(如果條件允許的話)

以下例子使用 continue 只輸出奇數

<body>
 <button onclick="checked()">輸入奇數</button>
 <p id="element"></p>
</body>

<script>
function checked() {
  let num = [];
  let element = document.getElementById("element");
  for (let i = 0; i < 10; i++) {
    if (i % 2 == 0) continue;
    num.push(i);
  }
  element.innerHTML = num;
}
</script>

小總結

這裡的三種類型循環:

  • while 每次跌代之前都要檢查條件
  • do..while 每次繼承後都要檢查條件。
  • for(;;) 每次繼承之前都要檢查條件,可以使用其他設置。

switch 語句

  • switch 語句可以替代多個 if 判斷
  • switch 語句為多個分支選擇的情況提供一個具體描述的方法
  • switch 語句有至少一個 case 代碼塊和一個可選的 default 代碼塊
switch(x) {
  case 'value1':  // if (x === 'value1')
    ...
    [break]

  case 'value2':  // if (x === 'value2')
    ...
    [break]

  default:
    ...
    [break]
}

比較x值與第一個case(也就是value1)是否嚴格定義,然後比較第二個case(value2)以此類推。

let a = 1;
switch (a) {
  case 3:
    alert("Is 3");
    break;
  case 4:
    alert("Is 4");
    break;
  default:
    alert("Not thing");
}

case 分組

共享同一段代碼的幾個 case 分支會被分在同一組

let a = 1;
switch (a) {
  case 3:
    alert("Is 3");
    break;
  case 4:  //(*)下面這兩個案例被分在一組
  case 5:
    alert("Is 4");
    break;
  default:
    alert("Not thing");
}
  • 現在 4 和 5 都會顯示相同的訊息。
  • case 4 在沒有 break 的情況下,會繼續往下執行,直到遇到 break 後停止。

類型很關鍵


在 "use strict" 環境下,被比較的值必須是相同類型的才能匹配

let arg = prompt("Enter a value?")
switch (arg) {
  case '3':
    alert( 'Is String 3' );
    break;

  case 3:
    alert( 'Is Number 3' );
    break;
  default:
    alert( 'An unknown value' )
}


因為 prompt 的結果是字串類型的 "3",不是嚴格相等於數字類型的 3,所以 case 3 不會執行,則視窗會跳出 Is String 3

函數聲明

使用函數聲明創建函數,看起來像這樣

function showMessage(){
  alert('Hello');
}

調用函數名

showMessage();

變量與函數的關係

局部變量 在函數中聲明的變量只能在該函數內使用

function showMessage(){
  let message = 'Hello';
  alert(message);
}
showMessage();
alert(message); //錯誤,無法使用這個變量

外部變量 函數也可以訪問外部變量

let userName = "John";
function showMessage() {
  let message = `Hello ${userName}`;
  alert(message);
}
showMessage(); //Hello John

全局變量 任何函數之外的聲明都較全局變量,上述的 userName 都稱為全局變量

參數 可以使用參數來將任意的數據傳遞給函數

let from = 'fromName';
let text = 'textName';

showMessage(from,text);

function showMessage(from, text){
 alert(`${from} and ${text}`)
}

默認值 如果未提供參數,則其值是 undefined

以上述的例子來說,我們可以為 text 加上預設值

let from = "fromName";

showMessage(from);
function showMessage(from, text = 'fromTextName') {
  alert(`${from} and ${text}`);
}
// fromName and fromTextName

現在 text 參數未被傳遞,它將得到 'fromTextName'的字串
但它可以是更複雜的表達式,只有在缺少參數時才會計算和分配表達式,因此,這也是可能的

function showMessage(from, text=anotherFunction()){
  anotherFunction() //僅在沒有給定文本時執行
}
Tips
在JavaScript 中,每次函數在沒帶個別參數的情況下被調用,默認參數會被計算出來。
上述的 showMessage() 不帶 text 參數被調用時,anotherFunction() 會被調用

反回值 函數可將一個值返回到調用代碼中作結果

function sum(a,b){
  return a+b;
}

let result = sum(1,2);
alert(result)

在沒有值的情況下使用 return 可能會導致函數立即退出

function showMessage(age){
  return;
}

showMessage(18)
Tips
如果我們想要將返回的表達式跨行,我們應該在 return 的同一行開始寫此表達式
return (
  some + long + expression
  + or +
  whatever * f(a) + f(b)
)

函數命名

函數是行為。所以它們的名字通常是動詞。它應該簡短且盡可能精準描述函數的作用。這樣讀代碼的人就能得到關於該函數作用的指示。

一種普遍的做法是用動詞前綴來開始一個函數,這個前綴模糊地描述了這個動作。團隊內部必須就前綴的含義達成一致。

函數開始:

  • "get"    返回值
  • "calc"   計算
  • "create" 創建
  • "check"  檢查並返回 boolean 值,等


這類名字的示例:

  • showMessage(..)     //顯示訊息
  • getAge(..)                //返回年齡
  • calcSum(..)              //加總計算並返回結果
  • createFrom(..)             /創建表單並返回它
  • checkPermission(..)    //檢查權限並返回 true/false
Tips
一個函數做一件事
一個函數應該完全按照它的名字做,而不是做更多和自身無關的功能。
兩個獨立的操作通常需要兩個函數,即使它們通常被一起調用(在這種情況下,我們可以創建第三個函數來調用這兩個函數)。
getAge 如果它顯示一個 alert 和這個 age (只應該得到),那就是有問題的
createFrom 如果它修改文檔,向它添加一個表單(只應該創建它並返回),那就是有問題的
checkPermission 如果顯示 access granted/denied 消息(只應該執行檢查並返回結果),那就錯誤。
這些例子具有前綴的共同含義。它們對您的意義取決於您和您的團隊。也許您的代碼行為不同是很正常的。但是您應該對前綴意味著什麼,前綴函數能做什麼和不能做什麼有一個明確的理解。所有相同的前綴函數都應遵守規則。團隊應該分享知識。

函數聲明像這樣:

function name(parameters, delimited, by, comma) {
  /* code */
}

作為參數傳遞給函數,值被複製到其局部變量
函數可以訪問外部變量。但它只能從內到外起作用。函數外部的代碼看不到它的局部變量。
函數可以返回值。如果沒有,則其結果是undefined。
為了使代碼簡潔易懂,建議在函數中主要使用局部變量和參數,而不是外部變量。

JS 看到這裡
https://zh.javascript.info/function-expressions-arrows

參考資料

  1. JavaScript 基礎知識
  2. 「每日一题」JS 中的 Symbol 是什麼?