App Script 特殊標記符號(Scriptlet) 解析
更新日期: 2023 年 7 月 31 日
在 Google Apps Script 中,有一種稱為特殊的語法:Scriptlets。
它主要的目的,是允許你在一般的 HTML 檔案中,嵌入 Apps Script 代碼,並在 Google 架設的伺服器中計算運算的結果。
藉由這些 Scriptlets 讓 HTML 頁面也可以動態生成內容,提供了一種強大的機制,創造一個結合前端與後端的網頁應用程序(Web App)。
特殊標記符號 Scriptlets 有三種類型語法:
- 標準指令碼數:<? … ?>
- 列印腳本:<?= … ?>
- 強制列印指令碼:<?!= … ?>
以下為你一一介紹對應內容:
標準指令碼數 :<? … ?>
當我們在談論 <? ?>
標籤時,這基本上是在說,你可以在此標籤中執行一些 Apps Script 代碼,但這段代碼的結果不會直接顯示在你的網頁上。
這就像在 HTML 網頁私底下在做一些事情,而使用者卻看不見這個過程。
例如,你可能想要在一個 HTML 文件中將一個數值並分配給一個變數,你可以使用 <? ?> 標籤來完成這個任務。以下是一個範例:
<? var myNumber = 5; ?>
在這個例子中,你創建了一個新的變數 myNumber 並分配了數值 5。這是在後端執行的代碼,因此使用者看不到這個過程。
另一種使用 <? ?> 標籤的情境,是當你想要在你的 HTML 文件中,使用條件語句(例如 if)或循環(例如 for)。以下是一個範例:
<? for (var i = 0; i < 5; i++) { ?>
<p>This is paragraph number <?= i + 1 ?>.</p>
<? } ?>
在這個例子中,你使用了一個 for 迴圈動態生成 5 個段落。
每一個段落的內容都依賴於變量 i。你可以看到,這裡使用了 <? ?> 標籤來包含 for 迴圈的開始和結束,同時還在 p 標籤中插入變量 i 的值到每個段落的內容中。
乍看之下,你可能會覺得代碼異常詭異:怎麼可以一段是 JavaScript 代碼,下一段又是 HTML 代碼,HTML 代碼中又嵌入 JavaScript 代碼,然後又 JavaScript 代碼?
你這個想法非常好!確實,第一眼這可能看起來很混亂。
但是事實上,若以電腦的角度切入,它卻能很好地查看這些代碼。
這是因為,當我們在 HTML 文件中使用這些 <? ?> 標籤時,電腦會對它們做特殊的處理。
讓我們同樣在以此代碼為例:
<? for (var i = 0; i < 5; i++) { ?>
<p>This is paragraph number <?= i + 1 ?>.</p>
<? } ?>
這裡發生的事情是:
- 當電腦看到「<?」 標籤,它就知道接下來的代碼將是 Apps Script 代碼,且有效區間是在它遇到與之匹配的 「?>」 標籤為止。
- 因此,當它看到 for (var i = 0; i < 5; i++) {,它會執行這段 Apps Script 代碼。
- 當電腦遇到 ?> 標籤,它就知道 Apps Script 代碼已經結束了,並且接下來的將是 HTML 代碼,直到它遇到下一個 <? 標籤為止。
- 當它看到 <p>This is paragraph number ,它會將這段文本直接插入到生成的 HTML 中。
- 當電腦遇到 <? 標籤,它知道這是一個 Apps Script 表達式,並且將這個表達式的結果插入到生成的 HTML 中。
- 因此,當它看到 <?= i + 1 ?>,它將計算 i+1 的值(因為這是在 for 迴圈中,所以 i 的值會改變),並將這個值插入到生成的 HTML 中。
- 最後,當電腦遇到 </p>,它將這段 HTML 代碼插入並生成到頁面中。
- 然後當它遇到 <? } ?> 時,它知道這是 Apps Script 代碼中 for 迴圈的結尾,因此迴圈結束。
總的來說,雖然這種混合 Apps Script 代碼和 HTML 代碼的方式可能看起來很混亂,但是電腦能夠很好地處理它。
這主要得益於<? 與 ?> 標籤,它們清楚地指示了何時開始和結束 Apps Script 代碼。
常見問題: <? ?> 的功能,是不是跟 <script></script> 的功能類似,都是要在 HTML 檔案中,執行 JavaScript 的代碼?
是的,<? ?> 和 <script></script> 在一定程度上功能是相似的。
因為他們都允許在 HTML 文件中嵌入和執行 JavaScript 代碼。然而,他們之間也有一些重要的差異。
一、<script></script>:在 HTML 中,我們使用這種語法來嵌入和執行 JavaScript 代碼。代碼被瀏覽器讀取並在客戶端(即使用者的電腦)上執行。
這對於增加網頁互動性,如響應按鈕點擊、動態修改頁面內容等來說非常有用。
這裡的 JavaScript 代碼可能直接位於 <script></script> 標籤內,例如:
<script>
function myFunction() {
alert('Hello, World!');
}
</script>
二、<? ?>:這是 Google Apps Script HTML 服務中的一種語法,允許你在 HTML 文件中嵌入 Apps Script 代碼並在 Google 的伺服器上執行它。
這可以讓你在 HTML 中直接使用 Apps Script 的功能,例如讀取和寫入 Google 試算表,或者使用其他 Google 服務。
這裡的代碼在 HTML 文件被時執行,是在伺服器處理(或「評估」),而不是在客戶端。例如:
<? let data = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Data").getRange("A1:B2").getValues(); ?>
在這裡,Apps Script 代碼在 <? ?>
中執行,並從試算表中獲取資料。
所以總的來說,雖然 <script></script> 和 <? ?> 都可以在 HTML 中執行代碼,但他們運行的地點和方式不同。
<script></script> 是在客戶端執行 JavaScript,而 <? ?> 是在 Google 的伺服器上執行 Apps Script 代碼。
列印腳本: <?= … ?>
<?= … ?> 是 Google Apps Script 中的 「輸出特殊字元」。
這種字元可以讓你在 HTML 模板文件中嵌入 Apps Script 代碼,並將該代碼函數運作後的返回值(return value),輸出到 HTML 中。
例如,你有一個 Apps Script 變數 myVar,該變數被賦予一個字串。
let myVar = "Hello,world!";
若你希望將該變數的值輸出到一個 HTML 段落中,你可以這樣寫:
<p><?= myVar ?></p>
這樣當 HTML 模板被 Google 伺服器轉譯時,<?= myVar ?> 會被替換為 myVar
的值。所以,如果 myVar 是 「Hello, world!」,那麼評估後的 HTML 會是:
<p>Hello, world!</p>
強制列印指令碼 :<?!= … ?>
<?!= … ?> 這種標記的功能與 <?= … ?> 很類似,都是用來將 Apps Script 的變量或函數的返回值插入到 HTML 中。
然而,這兩種標記在處理返回值的方式上有所不同。
當你使用 <?= … ?> 標記時,Google Apps Script 會自動將插入的值轉換為 HTML 安全的文本。
這意味著它會自動將一些特殊字符(如 <、>、& 等)轉換為對應的 HTML 實體(例如,< 會被轉換為 <
),以防止這些字符被瀏覽器誤解為 HTML 代碼。
然而,當你使用 <?!= … ?> 標記時,Google Apps Script 就不會對插入的值進行這種轉換。
它將直接將值插入到 HTML 中,即使該值包含可能被瀏覽器誤解的特殊字符。
舉例來說,若我們有一個 Apps Script變量 myVar ,值為「<b>Hello,world!</b>」,這是一段簡單的HTML代碼,其中 <b> 是使文字加粗的HTML標籤。
如果你在你的HTML模板文件中這樣寫:
<p><?= myVar ?></p>
那麼,當 Google Apps Script 將此模板變為HTML時,它會將 <
和 >
轉換成對應的HTML實體,結果將為:
<p><b>Hello, world!</b></p>
所以在瀏覽器裡,這段HTML會顯示為:<b>Hello,world!</b>(不會被加粗,因為 <
和 >
被轉換了)
但如果你寫為:
<p><?!= myVar ?></p>
當 Apps Script 將此模板變為HTML時,它不會對 <
和 >
進行轉換,結果將為:
<p><b>Hello, world!</b></p>
所以在瀏覽器裡,這段HTML會顯示為:Hello, world!(會被加粗,因為 <
和 >
被視為HTML標籤)。
這就是<?= … ?>和 <?!= … ?> 之間的主要差異。
請注意,由於 <?!= ?>
不會對值進行轉換,因此使用它有一定的安全風險。
如果你插入的值包含來自不可信來源的數據(例如,用戶輸入的內容),那麼駭客可能利用這種可以轉譯的特性,輸入特定可執行的程式碼,導致網站執行未知的任務,產生跨站腳本攻擊(XSS)。
在這種情況下,你應該避免使用<?!= … ?>,並使用 <?= … ?> 來確保插入的值是安全的。