หากคุณมีสคริปต์ที่ใช้รันไทม์ของ Rhino อยู่แล้ว และต้องการใช้ประโยชน์จากไวยากรณ์และฟีเจอร์ V8 คุณต้องย้ายข้อมูลสคริปต์ไปยัง V8
สคริปต์ส่วนใหญ่ที่เขียนโดยใช้รันไทม์ของ Rhino สามารถทำงานโดยใช้รันไทม์ V8 ได้โดยไม่ต้องมีการปรับ ข้อกำหนดเบื้องต้นเพียงข้อเดียวในการเพิ่มไวยากรณ์และฟีเจอร์ V8 ลงในสคริปต์ก็คือการเปิดใช้รันไทม์ V8
อย่างไรก็ตาม มีความไม่เข้ากันและความแตกต่างอื่นๆ เล็กน้อยที่อาจส่งผลให้สคริปต์ทำงานล้มเหลวหรือทำงานโดยไม่คาดคิดหลังจากเปิดใช้รันไทม์ V8 เมื่อย้ายสคริปต์ไปใช้ V8 คุณต้องค้นหาโปรเจ็กต์สคริปต์สำหรับปัญหาเหล่านี้และแก้ไขปัญหาที่พบ
ขั้นตอนการย้ายข้อมูล V8
เมื่อต้องการย้ายสคริปต์ไปยัง V8 ให้ทำตามขั้นตอนต่อไปนี้
- เปิดใช้รันไทม์ V8 สำหรับสคริปต์
- ตรวจสอบความไม่เข้ากันในรายการด้านล่างอย่างละเอียด ตรวจสอบสคริปต์เพื่อดูว่ามีความไม่เข้ากันหรือไม่ หากมีความเข้ากันไม่ได้อย่างน้อย 1 อย่าง ให้แก้ไขโค้ดสคริปต์เพื่อนำออกหรือหลีกเลี่ยงปัญหา
- ตรวจสอบความแตกต่างอื่นๆ ที่ระบุไว้ด้านล่างอย่างละเอียด ตรวจสอบสคริปต์เพื่อดูว่าความแตกต่างใดๆ ที่ระบุไว้ส่งผลต่อการทำงานของโค้ดหรือไม่ ปรับสคริปต์เพื่อแก้ไขลักษณะการทำงาน
- เมื่อแก้ไขความไม่เข้ากันที่พบหรือความแตกต่างอื่นๆ แล้ว คุณจะเริ่มอัปเดตโค้ดเพื่อใช้ไวยากรณ์ V8 และฟีเจอร์อื่นๆ ได้ตามต้องการ
- หลังจากแก้ไขโค้ดเสร็จแล้ว ให้ทดสอบสคริปต์อย่างละเอียดเพื่อดูว่าทำงานได้ตามที่คาดไว้
- หากสคริปต์เป็นเว็บแอปหรือส่วนเสริมที่เผยแพร่แล้ว คุณต้องสร้างเวอร์ชันใหม่ของสคริปต์ที่มีการปรับ V8 หากต้องการให้ผู้ใช้ใช้งานเวอร์ชัน V8 ได้ คุณต้องเผยแพร่สคริปต์ด้วยเวอร์ชันนี้อีกครั้ง
ความไม่เข้ากัน
น่าเสียดายที่รันไทม์เดิมของ Apps Script ที่มาจาก Rhino อนุญาตให้มีการทำงาน ECMAScript ที่ไม่เป็นไปตามมาตรฐานหลายอย่าง เนื่องจาก V8 เป็นไปตามข้อกำหนดมาตรฐาน ระบบจึงไม่รองรับลักษณะการทำงานเหล่านี้หลังจากการย้ายข้อมูล หากไม่แก้ไขปัญหาเหล่านี้จะทำให้เกิดข้อผิดพลาดหรือการทำงานของสคริปต์ที่ใช้งานไม่ได้เมื่อเปิดใช้รันไทม์ V8
ส่วนต่อไปนี้จะอธิบายการทำงานและขั้นตอนที่คุณต้องทำเพื่อแก้ไขโค้ดสคริปต์ในระหว่างการย้ายข้อมูลไปยัง V8
หลีกเลี่ยง for each(variable in object)
เพิ่มคำสั่ง for each (variable in object)
ลงใน JavaScript 1.6 แล้ว และนำออกเพื่อเปลี่ยนไปใช้ for...of
เมื่อย้ายข้อมูลสคริปต์ไปยัง V8 ให้หลีกเลี่ยงการใช้คำสั่ง for each (variable in object)
แต่ให้ใช้ for (variable in object)
แทน
// Rhino runtime var obj = {a: 1, b: 2, c: 3}; // Don't use 'for each' in V8 for each (var value in obj) { Logger.log("value = %s", value); } |
// V8 runtime var obj = {a: 1, b: 2, c: 3}; for (var key in obj) { // OK in V8 var value = obj[key]; Logger.log("value = %s", value); } |
หลีกเลี่ยง Date.prototype.getYear()
ในรันไทม์ของ Rhino เวอร์ชันเดิม
Date.prototype.getYear()
จะแสดงผลปีแบบ 2 หลักสำหรับปีตั้งแต่ 1900-1999 แต่จะแสดงปี 4 หลักสำหรับวันที่อื่นๆ ซึ่งเป็นลักษณะการทำงานใน JavaScript 1.2 และก่อนหน้า
ในรันไทม์ V8
Date.prototype.getYear()
จะแสดงผลปีลบด้วย 1900 แทนตามที่มาตรฐาน ECMAScript กำหนด
เมื่อย้ายข้อมูลสคริปต์ไปยัง V8 ให้ใช้ Date.prototype.getFullYear()
เสมอ ซึ่งจะแสดงผลปีที่เป็นเลข 4 หลักโดยไม่คำนึงถึงวันที่
หลีกเลี่ยงการใช้คีย์เวิร์ดที่สงวนไว้เป็นชื่อ
ECMAScript ห้ามไม่ให้ใช้คีย์เวิร์ดที่สงวนไว้บางรายการในชื่อฟังก์ชันและชื่อตัวแปร รันไทม์ของ Rhino อนุญาตให้ใช้คำเหล่านี้อยู่เป็นจำนวนมาก ดังนั้นหากโค้ดใช้คำเหล่านี้ คุณต้องเปลี่ยนชื่อฟังก์ชันหรือตัวแปร
เมื่อย้ายสคริปต์ไปใช้ V8 ให้หลีกเลี่ยงการตั้งชื่อตัวแปรหรือฟังก์ชันโดยใช้คีย์เวิร์ดที่สงวนไว้รายการใดรายการหนึ่ง
เปลี่ยนชื่อตัวแปรหรือฟังก์ชันเพื่อหลีกเลี่ยงการใช้ชื่อคีย์เวิร์ด ชื่อที่ใช้คีย์เวิร์ดโดยทั่วไปคือ class
, import
และ export
หลีกเลี่ยงการกำหนดตัวแปร const
ใหม่
ในรันไทม์ของ Rhino เดิม คุณประกาศตัวแปรโดยใช้ const
ได้ ซึ่งหมายความว่าค่าของสัญลักษณ์จะไม่มีการเปลี่ยนแปลงและระบบจะไม่สนใจการกำหนดสัญลักษณ์ในอนาคต
ในรันไทม์ V8 ใหม่ คีย์เวิร์ด const
จะเป็นไปตามมาตรฐานมาตรฐานและจะกำหนดให้กับตัวแปรที่ประกาศว่าเป็น const
ส่งผลให้เกิดข้อผิดพลาดรันไทม์ TypeError: Assignment to constant variable
เมื่อย้ายสคริปต์ไปใช้ V8 อย่าพยายามกำหนดค่าตัวแปร const
ใหม่ในกรณีต่อไปนี้
// Rhino runtime const x = 1; x = 2; // No error console.log(x); // Outputs 1 |
// V8 runtime const x = 1; x = 2; // Throws TypeError console.log(x); // Never executed |
หลีกเลี่ยงการใช้ลิเทอรัล XML และออบเจ็กต์ XML
ส่วนขยายที่ไม่เป็นไปตามมาตรฐานไปยัง ECMAScript นี้จะอนุญาตให้โปรเจ็กต์ Apps Script ใช้ไวยากรณ์ XML โดยตรง
เมื่อย้ายข้อมูลสคริปต์ไปยัง V8 ให้หลีกเลี่ยงการใช้ลิเทอรัล XML โดยตรงหรือออบเจ็กต์ XML
ให้ใช้ XmlService แทนเพื่อแยกวิเคราะห์ XML ดังนี้
// V8 runtime var incompatibleXml1 = <container><item/></container>; // Don't use var incompatibleXml2 = new XML('<container><item/></container>'); // Don't use var xml3 = XmlService.parse('<container><item/></container>'); // OK |
อย่าสร้างฟังก์ชันตัววนซ้ำที่กำหนดเองโดยใช้ __iterator__
JavaScript 1.7 เพิ่มฟีเจอร์เพื่ออนุญาตให้เพิ่มตัวทำซ้ำที่กำหนดเองลงใน CLA ใดๆ โดยการประกาศฟังก์ชัน __iterator__
ในต้นแบบของคลาสนั้น และจะเพิ่มฟีเจอร์ดังกล่าวลงในรันไทม์ของ Rhino ของ Apps Script เพื่ออำนวยความสะดวกสำหรับนักพัฒนาซอฟต์แวร์ อย่างไรก็ตาม ฟีเจอร์นี้ไม่เคยเป็นส่วนหนึ่งของมาตรฐาน ECMA-262 และถูกนำออกในเครื่องมือ JavaScript ที่เป็นไปตาม ECMAScript สคริปต์ที่ใช้ V8
ไม่สามารถใช้การสร้างตัววนซ้ำนี้
เมื่อย้ายข้อมูลสคริปต์ไปยัง V8 ให้หลีกเลี่ยงฟังก์ชัน __iterator__
เพื่อสร้างตัวทำซ้ำที่กำหนดเอง แต่ให้ใช้ ECMAScript 6 Iterators แทน
ลองพิจารณาการสร้างอาร์เรย์ต่อไปนี้
// Create a sample array var myArray = ['a', 'b', 'c']; // Add a property to the array myArray.foo = 'bar'; // The default behavior for an array is to return keys of all properties, // including 'foo'. Logger.log("Normal for...in loop:"); for (var item in myArray) { Logger.log(item); // Logs 0, 1, 2, foo } // To only log the array values with `for..in`, a custom iterator can be used. |
ตัวอย่างโค้ดต่อไปนี้แสดงวิธีสร้าง Iterator ในรันไทม์ของ Rhino และวิธีสร้างตัวทำซ้ำในรันไทม์ V8
// Rhino runtime custom iterator function ArrayIterator(array) { this.array = array; this.currentIndex = 0; } ArrayIterator.prototype.next = function() { if (this.currentIndex >= this.array.length) { throw StopIteration; } return "[" + this.currentIndex + "]=" + this.array[this.currentIndex++]; }; // Direct myArray to use the custom iterator myArray.__iterator__ = function() { return new ArrayIterator(this); } Logger.log("With custom Rhino iterator:"); for (var item in myArray) { // Logs [0]=a, [1]=b, [2]=c Logger.log(item); } |
// V8 runtime (ECMAScript 6) custom iterator myArray[Symbol.iterator] = function() { var currentIndex = 0; var array = this; return { next: function() { if (currentIndex < array.length) { return { value: "[${currentIndex}]=" + array[currentIndex++], done: false}; } else { return {done: true}; } } }; } Logger.log("With V8 custom iterator:"); // Must use for...of since // for...in doesn't expect an iterable. for (var item of myArray) { // Logs [0]=a, [1]=b, [2]=c Logger.log(item); } |
หลีกเลี่ยงการใช้วลี Catch แบบมีเงื่อนไข
รันไทม์ V8 ไม่รองรับคำสั่ง Keep แบบมีเงื่อนไขของ catch..if
เนื่องจากไม่เป็นไปตามข้อกำหนดมาตรฐาน
เมื่อย้ายข้อมูลสคริปต์ไปยัง V8 ให้ย้ายเงื่อนไขของการรับตำแหน่งภายในเนื้อหาของ Catch ดังนี้
// Rhino runtime try { doSomething(); } catch (e if e instanceof TypeError) { // Don't use // Handle exception } |
// V8 runtime try { doSomething(); } catch (e) { if (e instanceof TypeError) { // Handle exception } } |
หลีกเลี่ยงการใช้ Object.prototype.toSource()
JavaScript 1.3 มีเมธอด Object.prototype.toSource() ที่ไม่เคยเป็นส่วนหนึ่งของมาตรฐาน ECMAScript ใดๆ เลย โดยจะไม่รองรับใน รันไทม์ V8
เมื่อย้ายข้อมูลสคริปต์ไปยัง V8 ให้นำการใช้งาน Object.prototype.toSource() ออกจากโค้ด
ความแตกต่างอื่นๆ
นอกเหนือจากความไม่เข้ากันข้างต้นซึ่งอาจทำให้สคริปต์ล้มเหลวแล้ว ยังมีความแตกต่างอื่นๆ อีก 2-3 อย่างที่หากได้รับการแก้ไข อาจทำให้เกิดลักษณะการทำงานของสคริปต์ V8 ที่ไม่คาดคิด
ส่วนต่อไปนี้จะอธิบายวิธีอัปเดตโค้ดของสคริปต์เพื่อหลีกเลี่ยงเรื่องไม่คาดคิดที่ไม่คาดคิด
ปรับการจัดรูปแบบวันที่และเวลาเฉพาะภาษา
Date
เมธอด toLocaleString()
,
toLocaleDateString()
และ toLocaleTimeString()
ทำงานต่างกันในรันไทม์ V8 เมื่อเทียบกับ Rhino
ใน Rhino รูปแบบเริ่มต้นคือรูปแบบยาว และระบบจะไม่สนใจพารามิเตอร์ที่ส่งผ่าน
ในรันไทม์ V8 รูปแบบเริ่มต้นคือรูปแบบแบบสั้น และพารามิเตอร์ที่ส่งผ่านจะได้รับการจัดการตามมาตรฐาน ECMA (ดูรายละเอียดในเอกสารประกอบของ toLocaleDateString()
)
เมื่อย้ายสคริปต์ไปยัง V8 ให้ทดสอบและปรับความคาดหวังของโค้ดเกี่ยวกับผลลัพธ์ของวิธีวันที่และเวลาที่เจาะจงภาษา
// Rhino runtime var event = new Date( Date.UTC(2012, 11, 21, 12)); // Outputs "December 21, 2012" in Rhino console.log(event.toLocaleDateString()); // Also outputs "December 21, 2012", // ignoring the parameters passed in. console.log(event.toLocaleDateString( 'de-DE', { year: 'numeric', month: 'long', day: 'numeric' })); |
// V8 runtime var event = new Date( Date.UTC(2012, 11, 21, 12)); // Outputs "12/21/2012" in V8 console.log(event.toLocaleDateString()); // Outputs "21. Dezember 2012" console.log(event.toLocaleDateString( 'de-DE', { year: 'numeric', month: 'long', day: 'numeric' })); |
หลีกเลี่ยงการใช้ Error.fileName
และ Error.lineNumber
ในการยกเลิกเวลา V8 ออบเจ็กต์ JavaScript มาตรฐาน Error
ไม่รองรับ fileName
หรือ lineNumber
เป็นพารามิเตอร์ตัวสร้างหรือพร็อพเพอร์ตี้ออบเจ็กต์
เมื่อย้ายข้อมูลสคริปต์ไปยัง V8 ให้นำการอ้างอิง Error.fileName
และ Error.lineNumber
ออก
อีกวิธีหนึ่งคือการใช้ Error.prototype.stack
สแต็กนี้ไม่เป็นไปตามมาตรฐานเช่นกัน แต่รองรับทั้งใน Rhino และ V8 รูปแบบของสแต็กเทรซที่ทั้ง 2 แพลตฟอร์มสร้างขึ้นแตกต่างกันเล็กน้อย ดังนี้
// Rhino runtime Error.prototype.stack // stack trace format at filename:92 (innerFunction) at filename:97 (outerFunction) |
// V8 runtime Error.prototype.stack // stack trace format Error: error message at innerFunction (filename:92:11) at outerFunction (filename:97:5) |
ปรับการจัดการออบเจ็กต์ enum ที่มีสตริง
ในรันไทม์ของ Rhino ดั้งเดิม การใช้เมธอด JavaScript JSON.stringify()
ในออบเจ็กต์ enum จะแสดงผลเพียง {}
ใน V8 การใช้เมธอดเดียวกันบนออบเจ็กต์ enum จะแสดงชื่อ enum อีกครั้ง
เมื่อย้ายสคริปต์ไปยัง V8 ให้ทดสอบและปรับความคาดหวังของโค้ดเกี่ยวกับเอาต์พุตของ JSON.stringify()
ในออบเจ็กต์ enum
// Rhino runtime var enumName = JSON.stringify(Charts.ChartType.BUBBLE); // enumName evaluates to {} |
// V8 runtime var enumName = JSON.stringify(Charts.ChartType.BUBBLE); // enumName evaluates to "BUBBLE" |
ปรับการจัดการพารามิเตอร์ที่ไม่ได้กำหนด
ในรันไทม์ของ Rhino ดั้งเดิม การส่ง undefined
ไปยังเมธอดในรูปแบบพารามิเตอร์ส่งผลให้ส่งสตริง "undefined"
ไปยังเมธอดดังกล่าว
ใน V8 การส่ง undefined
ไปยัง Method เทียบเท่ากับการส่ง null
เมื่อย้ายสคริปต์ไปยัง V8 ให้ทดสอบและปรับความคาดหวังของโค้ดเกี่ยวกับพารามิเตอร์ undefined
// Rhino runtime SpreadsheetApp.getActiveRange() .setValue(undefined); // The active range now has the string // "undefined" as its value. |
// V8 runtime SpreadsheetApp.getActiveRange() .setValue(undefined); // The active range now has no content, as // setValue(null) removes content from // ranges. |
ปรับการจัดการ this
ทั่วโลก
รันไทม์ของ Rhino กำหนดบริบทพิเศษแบบโดยนัยสำหรับสคริปต์ที่ใช้รันไทม์ดังกล่าว
โค้ดสคริปต์จะทำงานในบริบทโดยนัยนี้ ซึ่งแตกต่างจาก this
ส่วนกลางจริง ซึ่งหมายความว่าการอ้างอิงไปยัง "this
ส่วนกลาง" ในโค้ดจะประเมินบริบทพิเศษจริงๆ ซึ่งมีเฉพาะโค้ดและตัวแปรที่กำหนดไว้ในสคริปต์ บริการ Apps Script ในตัวและออบเจ็กต์ ECMAScript จะไม่รวมอยู่ในการใช้ this
นี้ สถานการณ์นี้คล้ายกับโครงสร้าง JavaScript
// Rhino runtime // Apps Script built-in services defined here, in the actual global context. var SpreadsheetApp = { openById: function() { ... } getActive: function() { ... } // etc. }; function() { // Implicit special context; all your code goes here. If the global this // is referenced in your code, it only contains elements from this context. // Any global variables you defined. var x = 42; // Your script functions. function myFunction() { ... } // End of your code. }(); |
ใน V8 บริบทพิเศษโดยนัยจะถูกนำออก ระบบจะวางตัวแปรและฟังก์ชันร่วมที่กำหนดไว้ในสคริปต์ในบริบทส่วนกลางข้างบริการ Apps Script ในตัวและ ECMAScript ในตัว เช่น Math
และ Date
เมื่อย้ายสคริปต์ไปยัง V8 ให้ทดสอบและปรับความคาดหวังของโค้ดเกี่ยวกับการใช้งาน this
ในบริบทที่เป็นสากล ในกรณีส่วนใหญ่ ความแตกต่างจะเห็นได้เฉพาะในกรณีที่โค้ดของคุณตรวจสอบคีย์หรือชื่อพร็อพเพอร์ตี้ของออบเจ็กต์ this
ส่วนกลาง
// Rhino runtime var myGlobal = 5; function myFunction() { // Only logs [myFunction, myGlobal]; console.log(Object.keys(this)); // Only logs [myFunction, myGlobal]; console.log( Object.getOwnPropertyNames(this)); } |
// V8 runtime var myGlobal = 5; function myFunction() { // Logs an array that includes the names // of Apps Script services // (CalendarApp, GmailApp, etc.) in // addition to myFunction and myGlobal. console.log(Object.keys(this)); // Logs an array that includes the same // values as above, and also includes // ECMAScript built-ins like Math, Date, // and Object. console.log( Object.getOwnPropertyNames(this)); } |
ปรับการจัดการ instanceof
ในไลบรารี
การใช้ instanceof
ในคลังบนออบเจ็กต์ที่ส่งผ่านเป็นพารามิเตอร์ในฟังก์ชันจากโปรเจ็กต์อื่นอาจให้ผลลบลวงได้ ในรันไทม์ V8 โปรเจ็กต์และไลบรารีของโปรเจ็กต์จะทำงานในบริบทการดำเนินการที่ต่างกัน ดังนั้นจึงมีทั่วโลกและห่วงโซ่ต้นแบบที่แตกต่างกัน
โปรดทราบว่ากรณีนี้จะเกิดขึ้นเฉพาะในกรณีที่ไลบรารีใช้ instanceof
ในออบเจ็กต์ที่ไม่ได้สร้างในโปรเจ็กต์ของคุณ การใช้คีย์บนออบเจ็กต์ที่สร้างขึ้นในโปรเจ็กต์ควรจะทำงานได้ตามที่คาดไว้ ไม่ว่าจะเป็นในสคริปต์เดียวกันหรือสคริปต์อื่นภายในโปรเจ็กต์
หากโปรเจ็กต์ที่ทํางานใน V8 ใช้สคริปต์เป็นไลบรารี ให้ตรวจสอบว่าสคริปต์ใช้ instanceof
ในพารามิเตอร์ที่จะส่งจากโปรเจ็กต์อื่นหรือไม่ ปรับการใช้งาน instanceof
และใช้ตัวเลือกอื่นๆ ที่เป็นไปได้ตามกรณีการใช้งาน
อีกทางเลือกหนึ่งสำหรับ a instanceof b
คือการใช้ตัวสร้างของ a
ในกรณีที่คุณไม่ต้องค้นหาห่วงโซ่ต้นแบบทั้งห่วงโซ่เพียงตรวจสอบตัวสร้าง
การใช้งาน: a.constructor.name == "b"
ลองพิจารณาโครงการ A และโครงการ B โดยโครงการ A ใช้โครงการ B เป็นห้องสมุด
//Rhino runtime //Project A function caller() { var date = new Date(); // Returns true return B.callee(date); } //Project B function callee(date) { // Returns true return(date instanceof Date); } |
//V8 runtime //Project A function caller() { var date = new Date(); // Returns false return B.callee(date); } //Project B function callee(date) { // Incorrectly returns false return(date instanceof Date); // Consider using return (date.constructor.name == // “Date”) instead. // return (date.constructor.name == “Date”) -> Returns // true } |
อีกทางเลือกหนึ่งอาจเป็นการแนะนำฟังก์ชันที่ตรวจสอบ instanceof
ในโปรเจ็กต์หลัก และส่งฟังก์ชันนอกเหนือจากพารามิเตอร์อื่นๆ เมื่อเรียกใช้ฟังก์ชันไลบรารี จากนั้นคุณจะใช้ฟังก์ชันที่ส่งผ่านเพื่อตรวจสอบ instanceof
ภายในคลังได้
//V8 runtime //Project A function caller() { var date = new Date(); // Returns True return B.callee(date, date => date instanceof Date); } //Project B function callee(date, checkInstanceOf) { // Returns True return checkInstanceOf(date); } |
ปรับการส่งทรัพยากรที่ไม่ได้แชร์ไปยังไลบรารี
การส่งต่อทรัพยากรที่ไม่ได้แชร์จากสคริปต์หลักไปยังไลบรารีจะทำงานต่างกันในรันไทม์ V8
รันไทม์ของ Rhino จะส่งทรัพยากรที่ไม่ได้แชร์ไม่ได้ ไลบรารีจะใช้ทรัพยากรของตนเองแทน
ในรันไทม์ V8 การส่งทรัพยากรแบบไม่แชร์ไปยังไลบรารีจะทำงาน ไลบรารีใช้ทรัพยากรที่ไม่ได้แชร์ซึ่งผ่านแล้ว
และอย่าส่งทรัพยากรที่ไม่ได้แชร์เป็นพารามิเตอร์ฟังก์ชัน ให้ประกาศทรัพยากรที่ไม่ได้แชร์ในสคริปต์เดียวกับที่ใช้ทรัพยากรเหล่านั้นเสมอ
ลองพิจารณาโครงการ A และโครงการ B โดยโครงการ A ใช้โครงการ B เป็นห้องสมุด ในตัวอย่างนี้ PropertiesService
คือทรัพยากรที่ไม่ได้แชร์
// Rhino runtime // Project A function testPassingNonSharedProperties() { PropertiesService.getScriptProperties() .setProperty('project', 'Project-A'); B.setScriptProperties(); // Prints: Project-B Logger.log(B.getScriptProperties( PropertiesService, 'project')); } |
// V8 runtime // Project A function testPassingNonSharedProperties() { PropertiesService.getScriptProperties() .setProperty('project', 'Project-A'); B.setScriptProperties(); // Prints: Project-A Logger.log(B.getScriptProperties( PropertiesService, 'project')); } |
อัปเดตการเข้าถึงสคริปต์แบบสแตนด์อโลน
สำหรับสคริปต์แบบสแตนด์อโลนที่ทำงานในรันไทม์ V8 คุณต้องให้สิทธิ์ดูสคริปต์แก่ผู้ใช้เป็นอย่างน้อยเพื่อให้ทริกเกอร์ของสคริปต์ทำงานได้อย่างถูกต้อง