2021年8月28日 星期六

TensorFlow.js 學習筆記 (二) : Javascript ES6 的新語法 (中)

由於篇幅太長了, 將 ES6 新語法測試拆分成三部分, 這是第二部分. 

本系列之前的文章參考 :


參考書籍 :

Javascript 函數活用範例速查辭典 (博碩 2015, 山田祥寬)
Javascript Tensorflow.js 人工智慧教本 (碁峰 2020, 陳會安)


4. 解構指定 (destructing assignment) :

所謂解構指定就是指定敘述可以一次對多個變數賦值, Python 就有這個方便語法, 又稱為多重指定  (multiple assignment), 例如 :

a, b, c=1, True, "Hello"  
 
這敘述可以同時將 1 指派給 a, True 指派給 b, "Hello" 指派給 c. 有了這語法, 在 Python 要將兩個變數交換就很簡單, 不需要透過一個中間變數暫存, 只要一條敘述就解決 :

x, y=y, x

Javascript 在 ES6 也添加了這項功能, 其語法為 :

let [x1. x2. x3, ...]=[a1, a2, a3, ...]

等號兩邊個數不一定要相同, 若左邊比右邊少, 則右邊多出來的會被丟棄 (不會有語法錯誤); 反之, 若左邊的比右邊多, 則左邊多出來的變數其值為 undefined. 若要避免出現 undefined, 可在左邊的變數設定預設值, 例如 : 

let [x, y=0, z='a']=[1, 2]      //x=1, y=2, z='a'

也可以用逗號將對應的變數跳過去不承接, 例如 :

let [x, , z]=[1, 2, 3]   //x=1, z= 3, 其中 2 無變數承接

如果兩變數要交換, 語法如下 :

[x, y]=[y, x]

例如 : 


測試 4-1 : 變數的解構指定 [看原始碼]  

<!doctype html>
<html>
  <head>
   <meta charset="UTF-8">
   <title>ES6 測試</title>
  </head>
  <body>
    <script>
      let [a, b, c, d]=[1, 2, 3, 4];
      document.write("[a, b, c, d]=[1, 2, 3, 4]" + "<br>");
      document.write("a=" + a + "<br>");      //a=1
      document.write("b=" + b + "<br>");     //b=2
      document.write("c=" + c + "<br>");      //c=3
      document.write("d=" + d + "<br>");      //d=4
      [a, b, c, d]=[d, c, b, a];
      document.write("[a, b, c, d]=[d, c, d, a]" + "<br>");
      document.write("a=" + a + "<br>");       //a=4
      document.write("b=" + b + "<br>");      //b=3
      document.write("c=" + c + "<br>");       //c=2
      document.write("d=" + d + "<br>");      //d=1
      [a, b=0, c='a', d]=[1, 2];       //設定預設值
      document.write("[a, b=0, c='a', d]=[1, 2]" + "<br>");
      document.write("a=" + a + "<br>");      //a=1
      document.write("b=" + b + "<br>");      //b=2   (有指定, 不使用預設值)
      document.write("c=" + c + "<br>");      //c='a'  (無指定, 使用預設值)
      document.write("d=" + d + "<br>");      //d=undefined   (沒有預設值, 多出來的變數)
    </script>
  </body>
</html>

結果如下 :

[a, b, c, d]=[1, 2, 3, 4]
a=1
b=2
c=3
d=4
[a, b, c, d]=[d, c, d, a]
a=4
b=3
c=2
d=1
[a, b=0, c='a', d]=[1, 2]
a=1
b=2
c=a
d=undefined

解構指定也可以用在字串, 將字串解構指定給多個變數時, 字串將以字元為單位拆解依序指定給左方的多個變數, 例如 :



<!doctype html>
<html>
  <head>
   <meta charset="UTF-8">
   <title>ES6 測試</title>
  </head>
  <body>
    <script>
      let [a, b, c, d, e, f, g]="Hello World";
      document.write("[a, b, c, d, e, f, g]='Hello World'" + "<br>");
      document.write("a=" + a + "<br>");
      document.write("b=" + b + "<br>");
      document.write("c=" + c + "<br>");
      document.write("d=" + d + "<br>");
      document.write("e=" + e + "<br>");
      document.write("f=" + f + "<br>");
      document.write("g=" + g + "<br>");
      [a, , c, , e, , g]="Hello World";
      document.write("[a, , c, , e, , g]='Hello World'" + "<br>");
      document.write("a=" + a + "<br>");
      document.write("c=" + c + "<br>");
      document.write("e=" + e + "<br>");
      document.write("g=" + g + "<br>");
    </script>
  </body>
</html>

此例中第二次解構指定跳過了 b, d, f 變數不予承接, 結果如下 :

[a, b, c, d, e, f, g]='Hello World'
a=H
b=e
c=l
d=l
e=o
f=
g=W
[a, , c, , e, , g]='Hello World'
a=H
c=l
e=o
g=W


5. 樣板字串內插 :

Python 有很好用的字串內插功能, 可在字串中嵌入變數或運算式達到動態更改字串局部內容的功能. ES6 也支援這種功能, 這種字串外面不是用單引號或雙引號括起來, 而是使用反引號 (即 Tab 鍵上方那個按鍵), 變數或運算式使用 ${variable|expression} 方式嵌入字串中, 例如 :

let msg=`Hello ${name} !`   

這種字串又稱為樣版字面值 (template literals) 或樣版字串 (template string). 

例如 :



<!doctype html>
<html>
  <head>
   <meta charset="UTF-8">
   <title>ES6 測試</title>
  </head>
  <body>
    <script>
      let name="Tony";
      let msg=`Hello ${name} !`    //嵌入變數
      document.write(msg + "<br>");
      let [a, b, c, d]=[1, 2, 3, 4];
      msg=`Math.max(1, 2, 3, 4)=${Math.max(a, b, c, d)}`;   //嵌入運算式
      document.write(msg + "<br>");
    </script>
  </body>
</html>

結果如下 : 

Hello Tony !
Math.max(1, 2, 3, 4)=4


6. 展開運算子 :
 
ES6 新增了三個連續點號 ... 的運算子稱為展開運算子 (spread operator), 它可用在陣列或字串上, 其用途如下 :
  • 展開陣列元素
  • 複製, 串接, 合併陣列
  • 將字串之字元展開變成陣列
  • 展開陣列元素後傳入函式做為位置參數
例如 : 



<!doctype html>
<html>
  <head>
   <meta charset="UTF-8">
   <title>ES6 測試</title>
  </head>
  <body>
    <script>
      let arr1=[1, 2, 3, 4, 5];
      document.write(arr1 + "<br>");        //直接輸出陣列內容
      document.write(...arr1 + "<br>");     //輸出展開後的陣列內容
      let arr2=[...arr1];                                //複製陣列 arr1 為 arr2=arr1.concat()
      document.write(...arr2 + "<br>");
      let arr3=[11, 12, ...arr1, 13, 14];        //展開後插入到其他陣列中
      document.write(...arr3 + "<br>");
      let arr4=[...arr1, ...arr2];                     //串接兩個陣列=arr1.concat(arr2)
      document.write(...arr4 + "<br>");
      let arr5=[[1, 2, 3], [4, 5, 6]];              //二維陣列
      let arr6=[...arr5];                                //複製二維陣列
      document.write(arr6 + "<br>");        
      document.write(...arr6 + "<br>");     //展開二維陣列
      let str="你在說哈囉嗎?"; 
      let arr7=[...str];                                  //展開字串中的每一字元
      document.write(...arr7 + "<br>");
    </script>
  </body>
</html>

此例演示了展開運算子在陣列與字串上的操作, 高維陣列一樣可展開, 結果如下 : 

1,2,3,4,5
1,2,3,4,5
1,2,3,4,5
11,12,1,2,3,4,5,13,14
1,2,3,4,5,1,2,3,4,5
你,在,說,哈,囉,嗎,?

輸出在網頁上結果看起來似乎有展開跟沒展開一樣, 輸出到控制台就可看出差異, 例如 : 



<!doctype html>
<html>
  <head>
   <meta charset="UTF-8">
   <title>ES6 測試</title>
  </head>
  <body>
    <script>
      let arr1=[1, 2, 3, 4, 5];
      console.log(arr1);
      document.write(...arr1 + "<br>");
      let arr2=[...arr1];
      console.log(...arr2);
      let arr3=[11, 12, ...arr1, 13, 14];
      console.log(...arr3);
      let arr4=[...arr1, ...arr2];
      console.log(...arr4);
      let arr5=[[1, 2, 3], [4, 5, 6]];
      let arr6=[...arr5];
      console.log(arr6);
      console.log(...arr6);
      let str="你在說哈囉嗎?";
      let arr7=[...str];
      console.log(...arr7);
    </script>
  </body>
</html>

此例與上例差別僅在於輸出到控制台 (console) 而已, 結果如下 : 




可見二維陣列直接輸出與展開後再輸出是不一樣的, 點前面的箭頭可顯示其差異 : 




展開運算子也可以用來將陣列元素展開後傳入函式做為位置參數, 例如 : 



<!doctype html>
<html>
  <head>
   <meta charset="UTF-8">
   <title>ES6 測試</title>
  </head>
  <body>
    <script>
      function get_sum(a, b, c) {
        return a + b + c;
        }
      let arr=[1, 2, 3];
      let sum=get_sum(...arr);     //將陣列元素展開後傳入函式中
      document.write("sum=" + sum + "<br>");
    </script>
  </body>
</html>

結果如下 :

sum=6 

沒有留言 :