ใน Google 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
รันไทม์ V8 ของ Apps Script มีข้อจำกัดและความแตกต่างที่สำคัญบางประการเมื่อเทียบกับรันไทม์ JavaScript ทั่วไปอื่นๆ ดูรายละเอียดเพิ่มเติมได้ที่ข้อจำกัดของรันไทม์ Apps Script 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 ให้คลิกบันทึกการดำเนินการที่ด้านบนของโปรแกรมแก้ไขสคริปต์
ดูการดำเนินการ
หากต้องการดูประวัติการเรียกใช้สคริปต์ ให้เปิดโปรเจ็กต์ Apps Script แล้วคลิกการเรียกใช้ ทางด้านซ้าย
แผงการดำเนินการไม่มีบันทึกการประทับเวลาของการเรียกใช้บริการ Apps Script แต่ละรายการ
ใช้บริการ
console เพื่อสร้างข้อความบันทึกที่เหมาะสม บันทึกทั้งหมดที่สร้างด้วย
console จะปรากฏในแผงการดำเนินการ
ตัวอย่างไวยากรณ์ 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 หรือรวมโค้ดและการอ้างอิงไว้ในไฟล์สคริปต์เดียว (เครื่องมือติดตามปัญหา) - ลำดับการเรียกใช้ไฟล์: ระบบจะเรียกใช้ไฟล์สคริปต์ทั้งหมดในโปรเจ็กต์ใน ขอบเขตส่วนกลาง คุณควรหลีกเลี่ยงโค้ดระดับบนสุดที่มีผลข้างเคียง และตรวจสอบว่าได้กำหนดฟังก์ชันและคลาสก่อนที่จะนำไปใช้ในไฟล์ต่างๆ จัดเรียงไฟล์ในเอดิเตอร์อย่างชัดเจนหากมีทรัพยากรที่ขึ้นต่อกัน
เปิดใช้รันไทม์ 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, ค้นหารายงานปัญหาที่มีอยู่, รายงานข้อบกพร่องใหม่ และส่งคำขอฟีเจอร์ใหม่