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

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

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

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

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

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

ข้อยกเว้นอย่างหนึ่งคือออบเจ็กต์ลิเทอรัลได้รับอนุญาตให้ใช้คีย์เวิร์ดที่สงวนไว้ (ในรันไทม์ทั้งหมด)

function class() {}     // Syntax error in V8.
var obj = { class: 1 }; // Allowed.

หลีกเลี่ยงการกำหนดค่าใหม่ให้กับตัวแปร 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 คุณต้องใช้ for...of เมื่อข้ามผ่านอาร์เรย์ที่มีตัววนซ้ำที่กำหนดเอง เนื่องจาก for..in ไม่คาดหวังว่าจะได้รับ Iterable

หลีกเลี่ยง Clause Catch แบบมีเงื่อนไข

รันไทม์ V8 ไม่รองรับ Clause 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() ออกจากโค้ด

ข้อแตกต่างอื่นๆ

นอกเหนือจากความไม่เข้ากันที่กล่าวไว้ข้างต้นซึ่งอาจทำให้สคริปต์ทำงานไม่สำเร็จแล้ว ยังมีข้อแตกต่างอื่นๆ อีกเล็กน้อยที่อาจทำให้สคริปต์รันไทม์ 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() กับออบเจ็กต์ 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 ทั่วโลกจริง ซึ่งหมายความว่าการอ้างอิง "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 กับออบเจ็กต์ที่ไม่ได้สร้างในโปรเจ็กต์ของคุณ การใช้ `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); }

คำแนะนำเกี่ยวกับ JDBC ในรันไทม์ V8

เราได้เพิ่มฟีเจอร์ใหม่ลงในบริการ JDBC ด้วยรันไทม์ V8

ใช้ executeBatch สำหรับการดำเนินการแบบกลุ่ม

ใช้การดำเนินการ executeBatch(params) เพื่อดำเนินการฐานข้อมูลแบบกลุ่ม

ตัวอย่างต่อไปนี้แสดงวิธีแทรกหลายแถวลงในฐานข้อมูลโดยใช้การจัดกลุ่ม

นี่คือรันไทม์ Rhino (วิธีเก่า)

var conn = Jdbc.getCloudSqlConnection("jdbc:google:mysql://...");
var stmt = conn.prepareStatement("INSERT INTO employees (name, age) VALUES (?, ?)");
var params = [["John Doe", 30], ["John Smith", 25]];
for (var i = 0; i < params.length; i++) {
  stmt.setString(1, params[i][0]);
  stmt.setInt(2, params[i][1]);
  stmt.execute();
}

นี่คือรันไทม์ V8 (วิธีใหม่)

var conn = Jdbc.getCloudSqlConnection("jdbc:google:mysql://...");
var stmt = conn.prepareStatement("INSERT INTO employees (name, age) VALUES (?, ?)");
var params = [["John Doe", 30], ["John Smith", 25]];
stmt.executeBatch(params);

ใช้ getRows เพื่อดึงข้อมูลชุดผลลัพธ์

ใช้ getRows(queryString) เพื่อดึงข้อมูลชุดผลลัพธ์ในการเรียกใช้ครั้งเดียว queryString ประกอบด้วยการเรียกใช้เมธอด Getter ของ JdbcResultSet ที่คั่นด้วยคอมมา เช่น "getString(1), getDouble('price'), getDate(3, 'UTC')". เมธอดที่รองรับ ได้แก่ เมธอด Getter ทั้งหมดที่รับผิดชอบในการอ่านข้อมูลคอลัมน์ เช่น getHoldability, getMetaData เป็นต้น ไม่รองรับ อาร์กิวเมนต์อาจเป็นดัชนีคอลัมน์จำนวนเต็ม (อิงตาม 1) หรือป้ายกำกับคอลัมน์สตริงที่อยู่ในเครื่องหมายคำพูดเดี่ยวหรือเครื่องหมายคำพูดคู่

ตัวอย่างต่อไปนี้แสดงวิธีดึงข้อมูลแถวจากชุดผลลัพธ์

นี่คือรันไทม์ Rhino (วิธีเก่า)

var conn = Jdbc.getCloudSqlConnection("jdbc:google:mysql://...");
var stmt = conn.createStatement();
var rs = stmt.executeQuery("SELECT name, age FROM employees");
while (rs.next()) {
  Logger.log(rs.getString('name') + ", " + rs.getInt('age'));
}

นี่คือรันไทม์ V8 (วิธีใหม่)

var conn = Jdbc.getCloudSqlConnection("jdbc:google:mysql://...");
var stmt = conn.createStatement();
var rs = stmt.executeQuery("SELECT name, age FROM employees");
var rows = rs.getRows("getString('name'), getInt('age')");
for (var i = 0; i < rows.length; i++) {
  Logger.log(rows[i][0] + ", " + rows[i][1]);
}

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

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