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

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

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

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

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

  1. เปิดใช้รันไทม์ V8 สำหรับสคริปต์ คุณตรวจสอบ runtimeVersion ได้โดยใช้ไฟล์ Manifest สำหรับโปรเจ็กต์ Apps Script
  2. โปรดอ่านความไม่เข้ากันต่อไปนี้อย่างละเอียด ตรวจสอบสคริปต์เพื่อดูว่ามีปัญหาความไม่เข้ากันหรือไม่ หากมีปัญหาความไม่เข้ากันอย่างน้อย 1 รายการ ให้ปรับโค้ดสคริปต์เพื่อนำปัญหาออกหรือหลีกเลี่ยงปัญหา
  3. โปรดอ่านความแตกต่างอื่นๆ ต่อไปนี้อย่างละเอียด ตรวจสอบสคริปต์เพื่อดูว่าความแตกต่างที่ระบุไว้ส่งผลต่อลักษณะการทำงานของโค้ดหรือไม่ ปรับสคริปต์เพื่อแก้ไขลักษณะการทำงาน
  4. เมื่อแก้ไขความไม่เข้ากันหรือความแตกต่างอื่นๆ ที่พบแล้ว คุณจะเริ่มอัปเดตรหัสเพื่อใช้ไวยากรณ์ V8 และฟีเจอร์อื่นๆ ได้
  5. หลังจากปรับโค้ดเสร็จแล้ว ให้ทดสอบสคริปต์อย่างละเอียดเพื่อให้แน่ใจว่าสคริปต์ทำงานได้ตามที่คาดไว้
  6. หากสคริปต์เป็นเว็บแอปหรือส่วนเสริมที่เผยแพร่ คุณต้อง สร้างเวอร์ชันใหม่ ของสคริปต์ที่มีการปรับ V8 และชี้การติดตั้งใช้งานไปยังเวอร์ชันที่สร้างขึ้นใหม่ หากต้องการให้ผู้ใช้ใช้เวอร์ชัน V8 ได้ คุณต้อง เผยแพร่สคริปต์อีกครั้งด้วยเวอร์ชันนี้
  7. หากใช้สคริปต์เป็นไลบรารี ให้สร้างการติดตั้งใช้งานแบบเวอร์ชันใหม่ของ สคริปต์ แจ้งเวอร์ชันใหม่นี้ไปยังสคริปต์และผู้ใช้ทั้งหมดที่ ใช้ไลบรารีของคุณ พร้อมแนะนำให้ผู้ใช้อัปเดตเป็นเวอร์ชันที่เปิดใช้ V8 ตรวจสอบว่าเวอร์ชันเก่าที่ใช้ Rhino ของไลบรารีไม่ได้ ใช้งานหรือเข้าถึงได้อีกต่อไป
  8. ตรวจสอบว่าไม่มีอินสแตนซ์ของสคริปต์ที่ยังทำงานในรันไทม์ Rhino รุ่นเดิม ตรวจสอบว่าการติดตั้งใช้งานทั้งหมด เชื่อมโยงกับเวอร์ชันที่อยู่ใน V8 เก็บการติดตั้งใช้งานเก่า ตรวจสอบเวอร์ชันทั้งหมดและ ลบเวอร์ชันที่ไม่ได้ใช้ V8 Runtime

ความไม่เข้ากัน

น่าเสียดายที่รันไทม์ของ 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 ได้เพิ่มฟีเจอร์ที่อนุญาตให้เพิ่มตัววนซ้ำที่กำหนดเองลงในคลาสใดก็ได้ โดยการประกาศฟังก์ชัน __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 แบบมีเงื่อนไข catch..if เนื่องจากไม่เป็นไปตามมาตรฐาน

เมื่อย้ายข้อมูลสคริปต์ไปยัง V8 ให้ย้ายเงื่อนไข catch ทั้งหมดไปไว้ใน ส่วนเนื้อหาของ 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 ก็ได้ สแต็กนี้ยังไม่ใช่มาตรฐาน แต่รองรับใน V8 รูปแบบของ Stack Trace ที่สร้างขึ้นโดยทั้ง 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() ในออบเจ็กต์การแจงนับจะแสดงผล {} เท่านั้น

ใน 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 จริงทั่วโลก ซึ่งหมายความว่าการอ้างอิงถึง "global 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"

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