การย้ายข้อมูลสคริปต์ไปยังรันไทม์ V8

หากคุณมีสคริปต์ที่ใช้รันไทม์ของ Rhino อยู่แล้ว และต้องการใช้ประโยชน์จากไวยากรณ์และฟีเจอร์ V8 คุณต้องย้ายข้อมูลสคริปต์ไปยัง V8

สคริปต์ส่วนใหญ่ที่เขียนโดยใช้รันไทม์ของ Rhino สามารถทำงานโดยใช้รันไทม์ V8 ได้โดยไม่ต้องมีการปรับ ข้อกำหนดเบื้องต้นเพียงข้อเดียวในการเพิ่มไวยากรณ์และฟีเจอร์ V8 ลงในสคริปต์ก็คือการเปิดใช้รันไทม์ V8

อย่างไรก็ตาม มีความไม่เข้ากันและความแตกต่างอื่นๆ เล็กน้อยที่อาจส่งผลให้สคริปต์ทำงานล้มเหลวหรือทำงานโดยไม่คาดคิดหลังจากเปิดใช้รันไทม์ V8 เมื่อย้ายสคริปต์ไปใช้ V8 คุณต้องค้นหาโปรเจ็กต์สคริปต์สำหรับปัญหาเหล่านี้และแก้ไขปัญหาที่พบ

ขั้นตอนการย้ายข้อมูล V8

เมื่อต้องการย้ายสคริปต์ไปยัง V8 ให้ทำตามขั้นตอนต่อไปนี้

  1. เปิดใช้รันไทม์ V8 สำหรับสคริปต์
  2. ตรวจสอบความไม่เข้ากันในรายการด้านล่างอย่างละเอียด ตรวจสอบสคริปต์เพื่อดูว่ามีความไม่เข้ากันหรือไม่ หากมีความเข้ากันไม่ได้อย่างน้อย 1 อย่าง ให้แก้ไขโค้ดสคริปต์เพื่อนำออกหรือหลีกเลี่ยงปัญหา
  3. ตรวจสอบความแตกต่างอื่นๆ ที่ระบุไว้ด้านล่างอย่างละเอียด ตรวจสอบสคริปต์เพื่อดูว่าความแตกต่างใดๆ ที่ระบุไว้ส่งผลต่อการทำงานของโค้ดหรือไม่ ปรับสคริปต์เพื่อแก้ไขลักษณะการทำงาน
  4. เมื่อแก้ไขความไม่เข้ากันที่พบหรือความแตกต่างอื่นๆ แล้ว คุณจะเริ่มอัปเดตโค้ดเพื่อใช้ไวยากรณ์ V8 และฟีเจอร์อื่นๆ ได้ตามต้องการ
  5. หลังจากแก้ไขโค้ดเสร็จแล้ว ให้ทดสอบสคริปต์อย่างละเอียดเพื่อดูว่าทำงานได้ตามที่คาดไว้
  6. หากสคริปต์เป็นเว็บแอปหรือส่วนเสริมที่เผยแพร่แล้ว คุณต้องสร้างเวอร์ชันใหม่ของสคริปต์ที่มีการปรับ 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'));
}

//Project B function setScriptProperties() { PropertiesService.getScriptProperties() .setProperty('project', 'Project-B'); } function getScriptProperties( propertiesService, key) { return propertiesService.getScriptProperties() .getProperty(key); }

// V8 runtime
// Project A
function testPassingNonSharedProperties() {
  PropertiesService.getScriptProperties()
      .setProperty('project', 'Project-A');
  B.setScriptProperties();
  // Prints: Project-A
  Logger.log(B.getScriptProperties(
      PropertiesService, 'project'));
}

// Project B function setProperties() { PropertiesService.getScriptProperties() .setProperty('project', 'Project-B'); } function getScriptProperties( propertiesService, key) { return propertiesService.getScriptProperties() .getProperty(key); }

อัปเดตการเข้าถึงสคริปต์แบบสแตนด์อโลน

สำหรับสคริปต์แบบสแตนด์อโลนที่ทำงานในรันไทม์ V8 คุณต้องให้สิทธิ์ดูสคริปต์แก่ผู้ใช้เป็นอย่างน้อยเพื่อให้ทริกเกอร์ของสคริปต์ทำงานได้อย่างถูกต้อง