مروری بر زمان اجرا V8

در Apps Script و JavaScript، یک محیط زمان اجرا یا runtime شامل موتور جاوا اسکریپت است که کد اسکریپت را تجزیه و اجرا می‌کند. runtime قوانینی را برای نحوه دسترسی به حافظه، نحوه تعامل برنامه با سیستم عامل کامپیوتر و اینکه چه سینتکس برنامه‌ای قانونی است، ارائه می‌دهد. هر مرورگر وب یک محیط زمان اجرا برای جاوا اسکریپت دارد.

از لحاظ تاریخی، Apps Script توسط مفسر جاوا اسکریپت Rhino موزیلا پشتیبانی می‌شود. در حالی که Rhino روشی مناسب برای Apps Script جهت اجرای اسکریپت‌های توسعه‌دهندگان فراهم می‌کرد، Apps Script را به یک نسخه خاص جاوا اسکریپت ( ES5 ) نیز وابسته می‌کرد. توسعه‌دهندگان Apps Script نمی‌توانند از سینتکس و ویژگی‌های مدرن‌تر جاوا اسکریپت در اسکریپت‌هایی که از Rhino runtime استفاده می‌کنند، استفاده کنند.

برای رفع این مشکل، Apps Script اکنون توسط V8 runtime که کروم و Node.js را پشتیبانی می‌کند، پشتیبانی می‌شود. می‌توانید اسکریپت‌های موجود را به V8 منتقل کنید تا از سینتکس و ویژگی‌های مدرن جاوا اسکریپت بهره‌مند شوید.

این صفحه ویژگی‌های جدید فعال‌شده توسط V8 و نحوه‌ی فعال‌سازی V8 برای استفاده در اسکریپت‌های شما را شرح می‌دهد. مهاجرت اسکریپت‌ها به V8 مراحل مهاجرت اسکریپت‌های موجود برای استفاده از زمان اجرای V8 را شرح می‌دهد.

ویژگی‌های زمان اجرای V8

اسکریپت‌هایی که از زمان اجرای V8 استفاده می‌کنند، می‌توانند از ویژگی‌های زیر بهره‌مند شوند:

سینتکس مدرن ECMAScript

شما می‌توانید از سینتکس مدرن ECMAScript در اسکریپت‌هایی که توسط زمان اجرای V8 پشتیبانی می‌شوند، استفاده کنید. این سینتکس شامل let ، const و بسیاری از ویژگی‌های محبوب دیگر است.

برای مشاهده‌ی لیست کوتاهی از بهبودهای رایج در سینتکس‌های V8 که می‌توانید با استفاده از ران‌تایم V8 انجام دهید، به مثال‌های سینتکس V8 مراجعه کنید.

تشخیص عملکرد بهبود یافته

تشخیص تابع اسکریپت برنامه‌ها برای اسکریپت‌هایی که از V8 استفاده می‌کنند بهبود یافته است. زمان اجرای جدید این قالب‌های تعریف تابع را تشخیص می‌دهد:

      function normalFunction() {}
      async function asyncFunction() {}
      function* generatorFunction() {}

      var varFunction = function() {}
      let letFunction = function() {}
      const constFunction = function() {}

      var namedVarFunction = function alternateNameVarFunction() {}
      let namedLetFunction = function alternateNameLetFunction() {}
      const namedConstFunction = function alternateNameConstFunction() {}

      var varAsyncFunction = async function() {}
      let letAsyncFunction = async function() {}
      const constAsyncFunction = async function() {}

      var namedVarAsyncFunction = async function alternateNameVarAsyncFunction() {}
      let namedLetAsyncFunction = async function alternateNameLetAsyncFunction() {}
      const namedConstAsyncFunction = async function alternateNameConstAsyncFunction() {}

      var varGeneratorFunction = function*() {}
      let letGeneratorFunction = function*() {}
      const constGeneratorFunction = function*() {}

      var namedVarGeneratorFunction = function* alternateNameVarGeneratorFunction() {}
      let namedLetGeneratorFunction = function* alternateNameLetGeneratorFunction() {}
      const namedConstGeneratorFunction = function* alternateNameConstGeneratorFunction() {}

      var varLambda = () => {}
      let letLambda = () => {}
      const constLambda = () => {}

      var varAsyncLambda = async () => {}
      let letAsyncLambda = async () => {}
      const constAsyncLambda = async () => {}

فراخوانی متدهای شیء از طریق تریگرها و کال‌بک‌ها

اسکریپت‌هایی که از V8 استفاده می‌کنند می‌توانند متدهای شیء و متدهای استاتیک کلاس را از مکان‌هایی که قبلاً می‌توانستید متدهای کتابخانه را فراخوانی کنید، فراخوانی کنند. این مکان‌ها شامل موارد زیر است:

مثال V8 زیر استفاده از متدهای شیء را هنگام ساخت آیتم‌های منو در Google Sheets نشان می‌دهد:

function onOpen() {
  const ui = SpreadsheetApp.getUi(); // Or DocumentApp, SlidesApp, or FormApp.
  ui.createMenu('Custom Menu')
      .addItem('First item', 'menu.item1')
      .addSeparator()
      .addSubMenu(ui.createMenu('Sub-menu')
          .addItem('Second item', 'menu.item2'))
      .addToUi();
}

const menu = {
  item1: function() {
    SpreadsheetApp.getUi().alert('You clicked: First item');
  },
  item2: function() {
    SpreadsheetApp.getUi().alert('You clicked: Second item');
  }
}

مشاهده گزارش‌ها

Apps Script دو ​​سرویس ثبت وقایع ارائه می‌دهد: سرویس Logger و کلاس console . هر دوی این سرویس‌ها، گزارش‌ها را در یک سرویس ثبت وقایع Stackdriver می‌نویسند.

برای نمایش لاگ‌های Logger و console ، در بالای ویرایشگر اسکریپت، روی Execution log کلیک کنید.

مشاهده اعدام‌ها

برای مشاهده‌ی تاریخچه‌ی اجرای اسکریپت خود، پروژه‌ی Apps Script را باز کنید و در سمت چپ، روی Executions کلیک کنید.

مثال‌های سینتکس V8

در زیر لیست کوتاهی از ویژگی‌های نحوی محبوب موجود برای اسکریپت‌هایی که از زمان اجرای V8 استفاده می‌کنند، آمده است.

let و const

کلمات کلیدی let و const به شما امکان می‌دهند به ترتیب متغیرهای محلی با دامنه بلوکی و ثابت‌های با دامنه بلوکی تعریف کنید.

// V8 runtime
let s = "hello";
if (s === "hello") {
  s = "world";
  console.log(s);  // Prints "world"
}
console.log(s);  // Prints "hello"

const N = 100;
N = 5; // Results in TypeError
      

توابع پیکانی

توابع پیکانی روشی فشرده برای تعریف توابع درون عبارات ارائه می‌دهند.

// Rhino runtime
function square(x) {
  return x * x;
}

console.log(square(5));  // Outputs 25
      
// V8 runtime
const square = x => x * x;
console.log(square(5));  // Outputs 25

// Outputs [1, 4, 9]
console.log([1, 2, 3].map(x => x * x));
      

کلاس‌ها

کلاس‌ها ابزاری برای سازماندهی مفهومی کد با وراثت فراهم می‌کنند. کلاس‌ها در V8 در درجه اول از نظر نحوی نسبت به وراثت مبتنی بر نمونه اولیه جاوا اسکریپت، غنی‌تر هستند.

// V8 runtime
class Rectangle {
  constructor(width, height) { // class constructor
    this.width = width;
    this.height = height;
  }

  logToConsole() { // class method
    console.log(`Rectangle(width=${this.width}, height=${this.height})`);
  }
}

const r = new Rectangle(10, 20);
r.logToConsole();  // Outputs Rectangle(width=10, height=20)
      

تکالیف تخریبی

عبارات انتساب تخریبی روشی سریع برای تجزیه مقادیر از آرایه‌ها و اشیاء به متغیرهای مجزا هستند.

// Rhino runtime
var data = {a: 12, b: false, c: 'blue'};
var a = data.a;
var c = data.c;
console.log(a, c);  // Outputs 12 "blue"

var a = [1, 2, 3];
var x = a[0];
var y = a[1];
var z = a[2];
console.log(x, y, z);  // Outputs 1 2 3
      
// V8 runtime
const data = {a: 12, b: false, c: 'blue'};
const {a, c} = data;
console.log(a, c);  // Outputs 12 "blue"


const array = [1, 2, 3];
const [x, y, z] = array;
console.log(x, y, z);  // Outputs 1 2 3


      

الفبای قالب

قالب‌های لیترال، رشته‌های لیترال هستند که امکان استفاده از عبارات جاسازی‌شده را فراهم می‌کنند. آن‌ها به شما این امکان را می‌دهند که از دستورات پیچیده‌تر الحاق رشته‌ها اجتناب کنید.

// Rhino runtime
var name =
  'Hi ' + first + ' ' + last + '.';
var url =
  'http://localhost:3000/api/messages/'
  + id;
      
// V8 runtime
const name = `Hi ${first} ${last}.`;
const url =
  `http://localhost:3000/api/messages/${id}`;


      

پارامترهای پیش‌فرض

پارامترهای پیش‌فرض به شما امکان می‌دهند مقادیر پیش‌فرض را برای پارامترهای تابع در اعلان تابع مشخص کنید. این کار می‌تواند کد را در بدنه تابع ساده کند زیرا نیاز به اختصاص صریح مقادیر پیش‌فرض به پارامترهای از دست رفته را از بین می‌برد.

// Rhino runtime
function hello(greeting, name) {
    greeting = greeting || "hello";
    name = name || "world";
    console.log(
        greeting + " " + name + "!");
}

hello();  // Outputs "hello world!"
      
// V8 runtime
const hello =
  function(greeting="hello", name="world") {
      console.log(
        greeting + " " + name + "!");
  }

hello();  // Outputs "hello world!"

      

رشته‌های چند خطی

شما می‌توانید رشته‌های چندخطی را با استفاده از همان سینتکس template literals تعریف کنید. همانند template literals، این سینتکس به شما امکان می‌دهد از الحاق رشته‌ها جلوگیری کرده و تعاریف رشته را ساده کنید.

// Rhino runtime
var multiline = "This string is sort of\n"
+ "like a multi-line string,\n"
+ "but it's not really one.";
      
// V8 runtime
const multiline = `This on the other hand,
actually is a multi-line string,
thanks to JavaScript ES6`;
      

محدودیت‌های زمان اجرای V8

محیط اجرایی Apps Script V8 یک محیط استاندارد Node.js یا مرورگر نیست. این موضوع می‌تواند هنگام فراخوانی کتابخانه‌های شخص ثالث یا اقتباس نمونه‌های کد از سایر محیط‌های جاوا اسکریپت، منجر به مشکلات سازگاری شود.

API های در دسترس نیستند

APIهای استاندارد جاوا اسکریپت زیر در زمان اجرای Apps Script V8 در دسترس نیستند :

  • تایمرها : setTimeout ، setInterval ، clearTimeout ، clearInterval
  • جریان‌ها : ReadableStream ، WritableStream ، TextEncoder ، TextDecoder
  • APIهای وب : fetch ، FormData ، File ، Blob ، URL ، URLSearchParams ، DOMException ، atob ، btoa
  • رمزنگاری : crypto ، SubtleCrypto
  • اشیاء سراسری : window ، navigator ، performance ، process (Node.js)

از APIهای اسکریپت برنامه‌های زیر به عنوان جایگزین استفاده کنید:

برای APIهایی که جایگزین Apps Script ندارند، مانند TextEncoder ، گاهی اوقات می‌توانید از polyfill استفاده کنید. polyfill کتابخانه‌ای است که قابلیت‌های API را که به طور پیش‌فرض در محیط زمان اجرا در دسترس نیستند، تکرار می‌کند. قبل از استفاده از polyfill، مطمئن شوید که با محیط زمان اجرای V8 Apps Script سازگار است.

محدودیت‌های ناهمزمان

محیط اجرایی V8 از سینتکس‌های async و await و شیء Promise پشتیبانی می‌کند. با این حال، محیط اجرایی Apps Script اساساً همگام (synchronous) است.

  • ریزوظایف (پشتیبانی‌شده) : زمان اجرا، صف ریزوظایف (جایی که فراخوانی‌های Promise.then و await رخ می‌دهند) را پس از خالی شدن پشته فراخوانی فعلی پردازش می‌کند.
  • Macrotasks (پشتیبانی نمی‌شود) : Apps Script حلقه رویداد استانداردی برای macrotasks ندارد. توابعی مانند setTimeout و setInterval در دسترس نیستند.
  • استثنای WebAssembly : رابط برنامه‌نویسی کاربردی (API) وب‌اسمبلی تنها ویژگی داخلی است که به صورت غیرمسدودکننده در زمان اجرا عمل می‌کند و الگوهای کامپایل ناهمزمان خاصی (WebAssembly.instantiate) را امکان‌پذیر می‌سازد.

تمام عملیات ورودی/خروجی، مانند UrlFetchApp.fetch ، مسدود می‌شوند. برای دستیابی به درخواست‌های شبکه موازی، از UrlFetchApp.fetchAll استفاده کنید.

محدودیت‌های کلاس

زمان اجرای V8 محدودیت‌های خاصی در رابطه با ویژگی‌های کلاس مدرن ES6+ دارد:

  • فیلدهای خصوصی : فیلدهای کلاس خصوصی (برای مثال، #field ) پشتیبانی نمی‌شوند و باعث خطاهای تجزیه می‌شوند. برای کپسوله‌سازی واقعی، استفاده از closureها یا WeakMap را در نظر بگیرید.
  • فیلدهای استاتیک : اعلان مستقیم فیلدهای استاتیک درون بدنه کلاس (برای مثال، static count = 0; ) پشتیبانی نمی‌شود. ویژگی‌های استاتیک را پس از تعریف کلاس به آن اختصاص دهید (برای مثال، MyClass.count = 0; ).

محدودیت‌های ماژول

  • ماژول‌های ES6 : محیط اجرایی V8 از ماژول‌های ES6 ( import / export ) پشتیبانی نمی‌کند. برای استفاده از کتابخانه‌ها، یا باید از مکانیزم کتابخانه Apps Script استفاده کنید یا کد خود و وابستگی‌های آن را در یک فایل اسکریپت واحد قرار دهید. ( مسئله یاب )
  • ترتیب اجرای فایل : تمام فایل‌های اسکریپت در پروژه شما در یک محدوده سراسری اجرا می‌شوند. بهتر است از کد سطح بالا با عوارض جانبی اجتناب کنید و مطمئن شوید که توابع و کلاس‌ها قبل از استفاده در فایل‌ها تعریف شده‌اند. در صورت وجود وابستگی بین فایل‌های خود، آنها را به طور صریح در ویرایشگر مرتب کنید.

فعال کردن زمان اجرای V8

اگر اسکریپتی از محیط اجرایی راینو استفاده می‌کند، می‌توانید با انجام موارد زیر آن را به V8 تغییر دهید:

  1. پروژه Apps Script را باز کنید.
  2. در سمت چپ، روی پروژه کلیک کنید.
  3. کادر فعال کردن زمان اجرای Chrome V8 را علامت بزنید.

همچنین می‌توانید زمان اجرای اسکریپت را مستقیماً با ویرایش فایل مانیفست اسکریپت مشخص کنید:

  1. پروژه Apps Script را باز کنید.
  2. در سمت چپ، روی پروژه کلیک کنید.
  3. کادر انتخاب نمایش فایل مانیفست "appsscript.json" در ویرایشگر را علامت بزنید .
  4. در سمت چپ، روی Editor > appsscript.json کلیک کنید.
  5. در فایل مانیفست appsscript.json ، فیلد runtimeVersion را روی مقدار V8 تنظیم کنید.
  6. در بالا، روی پروژه کلیک کنید.

مهاجرت اسکریپت‌ها به V8 مراحل دیگری را که باید برای اطمینان از عملکرد خوب اسکریپت خود با استفاده از V8 انجام دهید، توضیح می‌دهد.

فعال کردن محیط اجرایی راینو

اگر اسکریپت شما از V8 استفاده می‌کند و باید آن را به نسخه اصلی راینو تغییر دهید، موارد زیر را انجام دهید:

  1. پروژه Apps Script را باز کنید.
  2. در سمت چپ، روی پروژه کلیک کنید.
  3. تیک گزینه‌ی «فعال کردن زمان اجرای Chrome V8» را بردارید.

روش دیگر، ویرایش مانیفست اسکریپت شماست:

  1. پروژه Apps Script را باز کنید.
  2. در سمت چپ، روی پروژه کلیک کنید.
  3. کادر انتخاب نمایش فایل مانیفست "appsscript.json" در ویرایشگر را علامت بزنید .
  4. در سمت چپ، روی Editor > appsscript.json کلیک کنید.
  5. در فایل مانیفست appsscript.json ، فیلد runtimeVersion را روی مقدار DEPRECATED_ES5 تنظیم کنید.
  6. در بالا، روی پروژه کلیک کنید.

چگونه اسکریپت‌های موجود را منتقل کنم؟

راهنمای مهاجرت اسکریپت‌ها به V8 مراحلی را که برای مهاجرت یک اسکریپت موجود برای استفاده از V8 باید انجام دهید، شرح می‌دهد. این شامل فعال کردن زمان اجرای V8 و بررسی اسکریپت برای هرگونه ناسازگاری شناخته شده است.

مهاجرت خودکار اسکریپت‌ها به V8

از ۱۸ فوریه ۲۰۲۰، گوگل به تدریج شروع به انتقال اسکریپت‌های موجودی که تست سازگاری خودکار ما را پشت سر می‌گذارند به V8 خواهد کرد. اسکریپت‌های آسیب‌دیده پس از انتقال، به طور عادی به کار خود ادامه می‌دهند.

اگر می‌خواهید یک اسکریپت را از مهاجرت خودکار خارج کنید، فیلد runtimeVersion را در مانیفست آن روی DEPRECATED_ES5 تنظیم کنید. پس از آن می‌توانید در هر زمان اسکریپت را به صورت دستی به V8 منتقل کنید .

چگونه اشکالات را گزارش کنم؟

راهنمای پشتیبانی توضیح می‌دهد که چگونه از Stack Overflow کمک برنامه‌نویسی بگیرید، گزارش‌های مشکلات موجود را جستجو کنید، اشکالات جدید را ثبت کنید و درخواست‌های ویژگی‌های جدید ارائه دهید.