ใน Apps Script และ JavaScript รันไทม์หรือสภาพแวดล้อมรันไทม์มี เครื่องมือ JavaScript ที่แยกวิเคราะห์และเรียกใช้โค้ดสคริปต์ รันไทม์มี กฎเกี่ยวกับวิธีเข้าถึงหน่วยความจำ วิธีที่โปรแกรมโต้ตอบกับ ระบบปฏิบัติการของคอมพิวเตอร์ และไวยากรณ์ของโปรแกรมที่ถูกต้อง เว็บเบราว์เซอร์แต่ละรายการมีสภาพแวดล้อมรันไทม์สำหรับ JavaScript
ในอดีต Apps Script ขับเคลื่อนด้วยตัวแปล JavaScript ของ Rhino จาก Mozilla แม้ว่า Rhino จะเป็นวิธีที่สะดวกสำหรับ Apps Script ในการเรียกใช้สคริปต์ของนักพัฒนาซอฟต์แวร์ แต่ก็ยังจำกัดให้ Apps Script ใช้ JavaScript เวอร์ชันที่เฉพาะเจาะจง (ES5) นักพัฒนา Apps Script ไม่สามารถใช้ไวยากรณ์และฟีเจอร์ JavaScript ที่ทันสมัยกว่าในสคริปต์ที่ใช้รันไทม์ Rhino
เพื่อแก้ไขข้อกังวลนี้ ตอนนี้ Apps Script รองรับรันไทม์ V8 ที่ขับเคลื่อน Chrome และ Node.js แล้ว คุณสามารถย้ายข้อมูลสคริปต์ที่มีอยู่ไปยัง V8 เพื่อใช้ประโยชน์จากไวยากรณ์และฟีเจอร์ JavaScript ที่ทันสมัย
หน้านี้จะอธิบายฟีเจอร์ใหม่ที่เปิดใช้โดย V8 และวิธีเปิดใช้ V8 เพื่อใช้ในสคริปต์ การย้ายข้อมูลสคริปต์ไปยัง V8 อธิบายขั้นตอนการย้ายข้อมูลสคริปต์ที่มีอยู่เพื่อใช้รันไทม์ V8
ฟีเจอร์ของรันไทม์ V8
สคริปต์ที่ใช้รันไทม์ V8 จะใช้ประโยชน์จากฟีเจอร์ต่อไปนี้ได้
ไวยากรณ์ ECMAScript ที่ทันสมัย
คุณสามารถใช้ไวยากรณ์ ECMAScript
สมัยใหม่ในสคริปต์ที่ขับเคลื่อนด้วยรันไทม์ V8 ไวยากรณ์นี้ประกอบด้วย let, const และฟีเจอร์ยอดนิยมอื่นๆ อีกมากมาย
ดูตัวอย่างไวยากรณ์ V8 เพื่อดูรายการสั้นๆ ของการปรับปรุงไวยากรณ์ยอดนิยมที่คุณทำได้โดยใช้รันไทม์ V8
การตรวจหาฟังก์ชันที่ดียิ่งขึ้น
ปรับปรุงการตรวจหาฟังก์ชัน Apps Script สำหรับสคริปต์ที่ใช้ V8 รันไทม์ใหม่ จะรู้จักรูปแบบคำจำกัดความของฟังก์ชันต่อไปนี้
function normalFunction() {} async function asyncFunction() {} function* generatorFunction() {} var varFunction = function() {} let letFunction = function() {} const constFunction = function() {} var namedVarFunction = function alternateNameVarFunction() {} let namedLetFunction = function alternateNameLetFunction() {} const namedConstFunction = function alternateNameConstFunction() {} var varAsyncFunction = async function() {} let letAsyncFunction = async function() {} const constAsyncFunction = async function() {} var namedVarAsyncFunction = async function alternateNameVarAsyncFunction() {} let namedLetAsyncFunction = async function alternateNameLetAsyncFunction() {} const namedConstAsyncFunction = async function alternateNameConstAsyncFunction() {} var varGeneratorFunction = function*() {} let letGeneratorFunction = function*() {} const constGeneratorFunction = function*() {} var namedVarGeneratorFunction = function* alternateNameVarGeneratorFunction() {} let namedLetGeneratorFunction = function* alternateNameLetGeneratorFunction() {} const namedConstGeneratorFunction = function* alternateNameConstGeneratorFunction() {} var varLambda = () => {} let letLambda = () => {} const constLambda = () => {} var varAsyncLambda = async () => {} let letAsyncLambda = async () => {} const constAsyncLambda = async () => {}
เรียกเมธอดออบเจ็กต์การโทรจากทริกเกอร์และการเรียกกลับ
สคริปต์ที่ใช้ V8 สามารถเรียกใช้เมธอดของออบเจ็กต์และเมธอดแบบคงที่ของคลาสจากที่ที่คุณเรียกใช้เมธอดของไลบรารีได้อยู่แล้ว สถานที่เหล่านี้ ได้แก่ สถานที่ต่อไปนี้
- ทริกเกอร์ของไฟล์ Manifest ของส่วนเสริม Google Workspace
- ทริกเกอร์ที่ติดตั้งได้
- รายการเมนูในเครื่องมือแก้ไขของ Google Workspace
- ฟังก์ชัน Callback ของผู้ใช้ เช่น ฟังก์ชันที่อธิบายไว้ในตัวอย่างโค้ด
ScriptApp.newStateToken()
ตัวอย่าง V8 ต่อไปนี้แสดงการใช้วิธีการของออบเจ็กต์เมื่อสร้างรายการเมนูใน Google ชีต
function onOpen() {
const ui = SpreadsheetApp.getUi(); // Or DocumentApp, SlidesApp, or FormApp.
ui.createMenu('Custom Menu')
.addItem('First item', 'menu.item1')
.addSeparator()
.addSubMenu(ui.createMenu('Sub-menu')
.addItem('Second item', 'menu.item2'))
.addToUi();
}
const menu = {
item1: function() {
SpreadsheetApp.getUi().alert('You clicked: First item');
},
item2: function() {
SpreadsheetApp.getUi().alert('You clicked: Second item');
}
}
ดูบันทึก
Apps Script มีบริการบันทึก 2 รายการ ได้แก่ Logger และคลาส console บริการทั้ง 2 รายการนี้
จะเขียนบันทึกลงในบริการ Stackdriver Logging เดียวกัน
หากต้องการแสดงบันทึก Logger และ console ให้คลิก
Execution log ที่ด้านบนของโปรแกรมแก้ไขสคริปต์
ดูการดำเนินการ
หากต้องการดูประวัติการดำเนินการของสคริปต์ ให้เปิดโปรเจ็กต์ Apps Script แล้วคลิกการดำเนินการ ทางด้านซ้าย
ตัวอย่างไวยากรณ์ V8
ต่อไปนี้คือรายการสั้นๆ ของฟีเจอร์ด้านไวยากรณ์ยอดนิยมที่พร้อมใช้งานสำหรับ สคริปต์ที่ใช้รันไทม์ V8
let และ const
คีย์เวิร์ด let
และ const
ช่วยให้คุณกำหนดตัวแปรเฉพาะที่ระดับบล็อกและค่าคงที่ระดับบล็อกได้ตามลำดับ
// V8 runtime let s = "hello"; if (s === "hello") { s = "world"; console.log(s); // Prints "world" } console.log(s); // Prints "hello" const N = 100; N = 5; // Results in TypeError |
ฟังก์ชันลูกศร
ฟังก์ชันลูกศร เป็นวิธีที่กะทัดรัดในการกำหนดฟังก์ชันภายในนิพจน์
// Rhino runtime function square(x) { return x * x; } console.log(square(5)); // Outputs 25 |
// V8 runtime const square = x => x * x; console.log(square(5)); // Outputs 25 // Outputs [1, 4, 9] console.log([1, 2, 3].map(x => x * x)); |
คลาส
คลาส เป็นวิธีจัดระเบียบโค้ดในเชิงแนวคิดด้วยการรับค่า คลาสใน V8 เป็นเพียงไวยากรณ์ที่ทำให้การสืบทอดตามต้นแบบของ JavaScript ดูง่ายขึ้น
// V8 runtime class Rectangle { constructor(width, height) { // class constructor this.width = width; this.height = height; } logToConsole() { // class method console.log(`Rectangle(width=${this.width}, height=${this.height})`); } } const r = new Rectangle(10, 20); r.logToConsole(); // Outputs Rectangle(width=10, height=20) |
การกำหนดค่าการทำลาย
การกำหนดค่าการแยกโครงสร้าง เป็นวิธีที่รวดเร็วในการแยกค่าจากอาร์เรย์และออบเจ็กต์ลงใน ตัวแปรที่แตกต่างกัน
// Rhino runtime var data = {a: 12, b: false, c: 'blue'}; var a = data.a; var c = data.c; console.log(a, c); // Outputs 12 "blue" var a = [1, 2, 3]; var x = a[0]; var y = a[1]; var z = a[2]; console.log(x, y, z); // Outputs 1 2 3 |
// V8 runtime const data = {a: 12, b: false, c: 'blue'}; const {a, c} = data; console.log(a, c); // Outputs 12 "blue" const array = [1, 2, 3]; const [x, y, z] = array; console.log(x, y, z); // Outputs 1 2 3 |
เทมเพลตลิเทอรัล
สตริงแทมเพลต คือสตริงลิเทอรัลที่อนุญาตให้ใช้นิพจน์แบบฝัง ซึ่งช่วยให้คุณหลีกเลี่ยง คำสั่งการต่อสตริงที่ซับซ้อนมากขึ้นได้
// Rhino runtime var name = 'Hi ' + first + ' ' + last + '.'; var url = 'http://localhost:3000/api/messages/' + id; |
// V8 runtime const name = `Hi ${first} ${last}.`; const url = `http://localhost:3000/api/messages/${id}`; |
พารามิเตอร์เริ่มต้น
พารามิเตอร์เริ่มต้น ช่วยให้คุณระบุค่าเริ่มต้นสำหรับพารามิเตอร์ของฟังก์ชันในการประกาศฟังก์ชันได้ ซึ่งจะช่วยลดความซับซ้อนของโค้ดในส่วนเนื้อหาของฟังก์ชันได้ เนื่องจากไม่จำเป็นต้องกำหนดค่าเริ่มต้นให้กับพารามิเตอร์ที่ขาดหายไปอย่างชัดเจน
// Rhino runtime function hello(greeting, name) { greeting = greeting || "hello"; name = name || "world"; console.log( greeting + " " + name + "!"); } hello(); // Outputs "hello world!" |
// V8 runtime const hello = function(greeting="hello", name="world") { console.log( greeting + " " + name + "!"); } hello(); // Outputs "hello world!" |
สตริงหลายบรรทัด
คุณกำหนดสตริงหลายบรรทัดได้โดยใช้ไวยากรณ์เดียวกันกับเทมเพลตสตริง ไวยากรณ์นี้ช่วยให้คุณหลีกเลี่ยงการต่อสตริงและลดความซับซ้อนของ คำจำกัดความสตริงได้เช่นเดียวกับ เทมเพลตสตริง
// Rhino runtime var multiline = "This string is sort of\n" + "like a multi-line string,\n" + "but it's not really one."; |
// V8 runtime const multiline = `This on the other hand, actually is a multi-line string, thanks to JavaScript ES6`; |
ข้อจำกัดของรันไทม์ V8
รันไทม์ V8 ของ Apps Script ไม่ใช่สภาพแวดล้อมมาตรฐานของ Node.js หรือเบราว์เซอร์ ซึ่งอาจทำให้เกิดปัญหาความเข้ากันได้เมื่อคุณเรียกใช้ไลบรารีของบุคคลที่สาม หรือปรับตัวอย่างโค้ดจากสภาพแวดล้อม JavaScript อื่นๆ
API ที่ไม่พร้อมใช้งาน
API มาตรฐานของ JavaScript ต่อไปนี้ไม่พร้อมใช้งานใน รันไทม์ V8 ของ Apps Script
- ตัวจับเวลา:
setTimeout,setInterval,clearTimeout,clearInterval - สตรีม:
ReadableStream,WritableStream,TextEncoder,TextDecoder - Web API:
fetch,FormData,File,Blob,URL,URLSearchParams,DOMException,atob,btoa - คริปโต:
crypto,SubtleCrypto - ออบเจ็กต์ส่วนกลาง:
window,navigator,performance,process(Node.js)
ใช้ Apps Script API ต่อไปนี้แทน
- ตัวจับเวลา: ใช้
Utilities.sleepสำหรับการหยุดชั่วคราวแบบซิงโครนัส ไม่รองรับตัวจับเวลาแบบอะซิงโครนัส - Fetch: ใช้
UrlFetchApp.fetch(url, params)เพื่อส่งคำขอ HTTP(S) - atob: ใช้
Utilities.base64Decodeเพื่อถอดรหัสสตริงที่เข้ารหัส Base64 - btoa: ใช้
Utilities.base64Encodeเพื่อเข้ารหัสสตริงใน Base64 - คริปโต: ใช้
Utilitiesสำหรับฟังก์ชันการเข้ารหัส เช่นcomputeDigestcomputeHmacSha256SignatureและcomputeRsaSha256Signature
สำหรับ API ที่ไม่มีทางเลือก Apps Script เช่น TextEncoder บางครั้งคุณสามารถใช้ Polyfill ได้ Polyfill คือไลบรารีที่จำลองฟังก์ชันการทำงานของ API ที่ไม่พร้อมใช้งานโดยค่าเริ่มต้นในสภาพแวดล้อมรันไทม์ ก่อนใช้ Polyfill ให้ตรวจสอบว่าเข้ากันได้กับรันไทม์ V8 ของ Apps Script
ข้อจำกัดแบบอะซิงโครนัส
รันไทม์ V8 รองรับไวยากรณ์ async และ await รวมถึงออบเจ็กต์ Promise
อย่างไรก็ตาม สภาพแวดล้อมรันไทม์ของ Apps Script เป็นแบบ
ซิงโครนัสโดยพื้นฐาน
- Microtask (รองรับ): รันไทม์จะประมวลผลคิว Microtask (ที่ซึ่งมีการเรียกกลับ
Promise.thenและการแก้ปัญหาawait) หลังจากที่สแต็กการเรียกใช้ปัจจุบันว่าง - มาโครทาสก์ (ไม่รองรับ): Apps Script ไม่มี
ลูปเหตุการณ์มาตรฐานสำหรับมาโครทาสก์ ฟังก์ชันอย่าง
setTimeoutและsetIntervalจะไม่พร้อมใช้งาน - ข้อยกเว้นของ WebAssembly: WebAssembly API เป็นฟีเจอร์ในตัวเพียงอย่างเดียว ที่ทำงานในลักษณะที่ไม่บล็อกภายในรันไทม์ ซึ่งช่วยให้ ใช้รูปแบบการคอมไพล์แบบอะซิงโครนัสที่เฉพาะเจาะจงได้ (WebAssembly.instantiate)
การดำเนินการ I/O ทั้งหมด เช่น
UrlFetchApp.fetch จะ
บล็อก หากต้องการส่งคำขอเครือข่ายพร้อมกัน ให้ใช้
UrlFetchApp.fetchAll
ข้อจำกัดของชั้นเรียน
รันไทม์ V8 มีข้อจำกัดเฉพาะเกี่ยวกับฟีเจอร์คลาส ES6+ สมัยใหม่ ดังนี้
- ฟิลด์ส่วนตัว: ไม่รองรับฟิลด์คลาสส่วนตัว (เช่น
#field) และจะทำให้เกิดข้อผิดพลาดในการแยกวิเคราะห์ ลองใช้ Closure หรือWeakMapเพื่อ การแคปซูลที่แท้จริง - ฟิลด์แบบคงที่: ระบบไม่รองรับการประกาศฟิลด์แบบคงที่โดยตรงภายในเนื้อหาของคลาส
(เช่น
static count = 0;) กำหนดพร็อพเพอร์ตี้แบบคงที่ ให้กับคลาสหลังจากกำหนดแล้ว (เช่นMyClass.count = 0;)
ข้อจำกัดของโมดูล
- โมดูล ES6: รันไทม์ V8 ไม่รองรับโมดูล ES6 (
import/export) หากต้องการใช้ไลบรารี คุณต้องใช้ กลไกไลบรารีของ Apps Script หรือรวมโค้ดและทรัพยากร Dependency ไว้ในไฟล์สคริปต์เดียว (เครื่องมือติดตามปัญหา) - ลำดับการเรียกใช้ไฟล์: ระบบจะเรียกใช้ไฟล์สคริปต์ทั้งหมดในโปรเจ็กต์ใน ขอบเขตส่วนกลาง คุณควรหลีกเลี่ยงโค้ดระดับบนสุดที่มีผลข้างเคียง และตรวจสอบว่าได้กำหนดฟังก์ชันและคลาสก่อนที่จะนำไปใช้ในไฟล์ต่างๆ จัดเรียงไฟล์ในเอดิเตอร์อย่างชัดเจนหากมีทรัพยากรที่ขึ้นต่อกัน
การเปิดใช้รันไทม์ V8
หากสคริปต์ใช้รันไทม์ Rhino คุณสามารถเปลี่ยนไปใช้ V8 ได้โดย ทำดังนี้
- เปิดโปรเจ็กต์ Apps Script
- คลิกการตั้งค่าโปรเจ็กต์ ทางด้านซ้าย
- เลือกช่องทำเครื่องหมายเปิดใช้รันไทม์ Chrome V8
หรือจะระบุรันไทม์ของสคริปต์โดยตรงได้ด้วยการ แก้ไขไฟล์ Manifest ของสคริปต์
- เปิดโปรเจ็กต์ Apps Script
- คลิกการตั้งค่าโปรเจ็กต์ ทางด้านซ้าย
- เลือกช่องทำเครื่องหมายแสดงไฟล์ Manifest "appsscript.json" ในเครื่องมือแก้ไข
- ทางด้านซ้าย ให้คลิกเอดิเตอร์ >
appsscript.json - ในไฟล์ Manifest ของ
appsscript.jsonให้ตั้งค่าฟิลด์runtimeVersionเป็นค่าV8 - คลิกบันทึกโปรเจ็กต์ ที่ด้านบน
การย้ายข้อมูลสคริปต์ไปยัง V8 อธิบาย ขั้นตอนอื่นๆ ที่คุณควรทำเพื่อให้สคริปต์ทำงานได้ดีโดยใช้ V8
การเปิดใช้รันไทม์ของ Rhino
หากสคริปต์ใช้ V8 และคุณต้องการเปลี่ยนให้ใช้รันไทม์ Rhino ดั้งเดิม ให้ทำดังนี้
- เปิดโปรเจ็กต์ Apps Script
- คลิกการตั้งค่าโปรเจ็กต์ ทางด้านซ้าย
- ยกเลิกการเลือกช่องทำเครื่องหมายเปิดใช้รันไทม์ Chrome V8
หรือจะแก้ไขไฟล์ Manifest ของสคริปต์ก็ได้
- เปิดโปรเจ็กต์ Apps Script
- คลิกการตั้งค่าโปรเจ็กต์ ทางด้านซ้าย
- เลือกช่องทำเครื่องหมายแสดงไฟล์ Manifest "appsscript.json" ในเครื่องมือแก้ไข
- ทางด้านซ้าย ให้คลิกเอดิเตอร์ >
appsscript.json - ในไฟล์ Manifest ของ
appsscript.jsonให้ตั้งค่าฟิลด์runtimeVersionเป็นค่าDEPRECATED_ES5 - คลิกบันทึกโปรเจ็กต์ ที่ด้านบน
ฉันจะย้ายข้อมูลสคริปต์ที่มีอยู่ได้อย่างไร
คำแนะนำการย้ายข้อมูลสคริปต์ไปยัง V8 อธิบายขั้นตอนที่คุณต้องทำเพื่อย้ายข้อมูลสคริปต์ที่มีอยู่ไปใช้ V8 ซึ่งรวมถึงการเปิดใช้รันไทม์ V8 และการตรวจสอบสคริปต์เพื่อหา ความไม่เข้ากันที่ทราบ
การย้ายข้อมูลสคริปต์ไปยัง V8 โดยอัตโนมัติ
ตั้งแต่วันที่ 18 กุมภาพันธ์ 2020 เป็นต้นไป Google จะเริ่มทยอยย้ายข้อมูลสคริปต์ที่มีอยู่ ซึ่งผ่านการทดสอบความเข้ากันได้อัตโนมัติของเราไปยัง V8 สคริปต์ที่ได้รับผลกระทบจะยังคงทำงานได้ตามปกติหลังจากการย้ายข้อมูล
หากต้องการเลือกไม่ให้สคริปต์ย้ายข้อมูลโดยอัตโนมัติ ให้ตั้งค่าฟิลด์
runtimeVersion
ในไฟล์ Manifest เป็น DEPRECATED_ES5 คุณเลือกที่จะย้ายข้อมูลสคริปต์ไปยัง V8 ด้วยตนเองได้ทุกเมื่อหลังจากนั้น
ฉันจะรายงานข้อบกพร่องได้อย่างไร
คู่มือการสนับสนุนอธิบายวิธีรับความช่วยเหลือด้านการเขียนโปรแกรมใน Stack Overflow, ค้นหารายงานปัญหาที่มีอยู่, ยื่นข้อบกพร่องใหม่ และส่งคำขอฟีเจอร์ใหม่