หากมีสคริปต์ที่ใช้รันไทม์ 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)
statements
แต่ให้ใช้ 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 เพิ่มฟีเจอร์ที่อนุญาตให้เพิ่มตัวดำเนินการวนซ้ำที่กำหนดเองลงในคลาสใดก็ได้โดยการประกาศฟังก์ชัน __iterator__
ในโปรโตไทป์ของคลาสนั้น นอกจากนี้ ฟีเจอร์นี้ยังเพิ่มลงในรันไทม์ Rhino ของ Apps Script เพื่ออำนวยความสะดวกให้แก่นักพัฒนาแอปด้วย อย่างไรก็ตาม ฟีเจอร์นี้ไม่เคยเป็นส่วนหนึ่งของมาตรฐาน ECMA-262 และถูกนำออกจากเครื่องมือ JavaScript ที่เป็นไปตามข้อกำหนด ECMAScript สคริปต์ที่ใช้ V8 ใช้การสร้างตัวดำเนินการวนซ้ำนี้ไม่ได้
เมื่อย้ายข้อมูลสคริปต์ไปยัง V8 ให้หลีกเลี่ยงการใช้ฟังก์ชัน __iterator__
เพื่อสร้างตัวดำเนินการซ้ำที่กำหนดเอง แต่ให้ใช้ตัวดำเนินการวนซ้ำ ECMAScript 6 แทน
ลองดูการสร้างอาร์เรย์ต่อไปนี้
// 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. |
ตัวอย่างโค้ดต่อไปนี้แสดงวิธีสร้างตัวดำเนินการวนซ้ำในรันไทม์ 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 ไม่รองรับประโยคเงื่อไขของ catch..if
เนื่องจากไม่เป็นไปตามมาตรฐาน
เมื่อย้ายข้อมูลสคริปต์ไปยัง V8 ให้ย้ายเงื่อนไขการจับข้อผิดพลาดภายในส่วนเนื้อหาของเงื่อนไขการจับข้อผิดพลาด
// 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 ทำงานไม่ถูกต้อง
ส่วนต่อไปนี้จะอธิบายวิธีอัปเดตโค้ดสคริปต์เพื่อหลีกเลี่ยงเหตุการณ์ที่ไม่คาดคิดเหล่านี้
ปรับการจัดรูปแบบวันที่และเวลาตามภาษา
เมธอด toLocaleString()
,
toLocaleDateString()
และ toLocaleTimeString()
ของ Date
จะทํางานต่างจากในรันไทม์ 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 Untime ออบเจ็กต์ 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
ไปยังเมธอดจะเทียบเท่ากับการส่ง 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
และใช้ทางเลือกอื่นๆ ที่เป็นไปได้ตาม Use Case ของคุณ
ทางเลือกหนึ่งสำหรับ a instanceof b
คือการใช้ตัวสร้างของ a
ในกรณีที่คุณไม่จําเป็นต้องค้นหาทั้งเชนโปรโตไทป์และเพียงตรวจสอบตัวสร้าง
การใช้งาน: a.constructor.name == "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 การผ่านทรัพยากรที่ไม่ใช่ส่วนกลางไปยังไลบรารีจะใช้งานได้ ไลบรารีใช้ทรัพยากรที่ไม่ใช่ส่วนกลางที่ส่งผ่าน
อย่าส่งทรัพยากรที่ไม่ใช่ส่วนกลางเป็นพารามิเตอร์ของฟังก์ชัน ประกาศทรัพยากรที่ไม่ใช่ส่วนกลางในสคริปต์เดียวกันที่ใช้ทรัพยากรนั้นเสมอ
พิจารณาโปรเจ็กต์ ก และโปรเจ็กต์ ข โดยที่โปรเจ็กต์ ก ใช้โปรเจ็กต์ ข เป็นไลบรารี ในตัวอย่างนี้ 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 คุณต้องให้สิทธิ์ผู้ใช้ดูสคริปต์เป็นอย่างน้อยเพื่อให้ทริกเกอร์ของสคริปต์ทํางานได้อย่างถูกต้อง