การย้ายข้อมูลสคริปต์ไปยังรันไทม์ 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) 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);
}
      

หลีกเลี่ยงการใช้นิพจน์ทั่วไปแบบมีเงื่อนไข

รันไทม์ V8 ไม่รองรับวลีคำสั่ง คุณจะเลือกตามเงื่อนไขของ 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 ทำงานไม่ถูกต้อง

ส่วนต่อไปนี้จะอธิบายวิธีอัปเดตโค้ดสคริปต์เพื่อหลีกเลี่ยงเหตุการณ์ที่ไม่คาดคิดเหล่านี้

ปรับการจัดรูปแบบวันที่และเวลาเฉพาะภาษา

เมธอด 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 ออบเจ็กต์ 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 การผ่านทรัพยากรที่ไม่ใช่ส่วนกลางไปยังไลบรารีจะใช้งานได้ ไลบรารีใช้ทรัพยากรที่ไม่ใช่ส่วนกลางที่ส่งผ่าน

อย่าส่งทรัพยากรที่ไม่ใช่ส่วนกลางเป็นพารามิเตอร์ฟังก์ชัน ประกาศทรัพยากรที่ไม่ใช่ส่วนกลางในสคริปต์เดียวกันที่ใช้ทรัพยากรนั้นเสมอ

ลองพิจารณาโครงการ 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 คุณต้องให้สิทธิ์ผู้ใช้ดูสคริปต์เป็นอย่างน้อยเพื่อให้ทริกเกอร์ของสคริปต์ทํางานได้อย่างถูกต้อง