Rhino çalışma zamanını kullanan mevcut bir komut dosyanız varsa ve V8 söz dizimi ile özelliklerinden yararlanmak istiyorsanız komut dosyasını V8'e taşımanız gerekir.
Rhino çalışma zamanı kullanılarak yazılan komut dosyalarının çoğu, herhangi bir ayarlama yapılmadan V8 çalışma zamanı kullanarak çalışabilir. Genellikle bir komut dosyasına V8 söz dizimini ve özelliklerini eklemenin tek ön koşulu, V8 çalışma zamanını etkinleştirmektir.
Bununla birlikte, V8 çalışma zamanı etkinleştirildikten sonra komut dosyasının başarısız olmasına veya beklenmedik bir şekilde davranmasına neden olabilecek küçük uyumsuzluklar ve başka farklılıklar vardır. Bir komut dosyasını V8 kullanacak şekilde taşırken, komut dosyası projesinde bu sorunları aramanız ve bulduğunuz çözümleri düzeltmeniz gerekir.
V8 taşıma prosedürü
Bir komut dosyasını V8'e taşımak için şu prosedürü uygulayın:
- Komut dosyası için V8 çalışma zamanını etkinleştirin.
- Aşağıda listelenen uyumsuzlukları dikkatlice inceleyin. Uyumsuzluklardan herhangi birinin olup olmadığını belirlemek için komut dosyanızı inceleyin. Bir veya daha fazla uyumsuzluk varsa, sorunu kaldırmak veya önlemek için komut dosyası kodunuzu düzenleyin.
- Aşağıda listelenen diğer farklılıkları dikkatlice inceleyin. Listelenen farklılıklardan herhangi birinin kodunuzun davranışını etkileyip etkilemediğini belirlemek için komut dosyanızı inceleyin. Davranışı düzeltmek için komut dosyanızı düzenleyin.
- Tespit edilen uyumsuzlukları veya diğer farklılıkları düzelttikten sonra, kodunuzu istediğiniz şekilde V8 söz dizimini ve diğer özellikleri kullanacak şekilde güncellemeye başlayabilirsiniz.
- Kod ayarlamalarınızı bitirdikten sonra, beklendiği gibi işlediğinden emin olmak için komut dosyanızı kapsamlı bir şekilde test edin.
- Komut dosyanız bir web uygulaması veya yayınlanmış bir eklenti ise V8 düzenlemeleriyle komut dosyasının yeni bir sürümünü oluşturmanız gerekir. V8 sürümünü kullanıcılara sunmak için komut dosyasını bu sürümle yeniden yayınlamanız gerekir.
Uyumsuzluklar
Orijinal Rhino tabanlı Apps Komut Dosyası çalışma zamanı, maalesef bazı standart olmayan ECMAScript davranışına izin vermiştir. V8 standartlara uygun olduğundan bu davranışlar taşıma işleminden sonra desteklenmez. Bu sorunların düzeltilmemesi, V8 çalışma zamanı etkinleştirildikten sonra hatalara veya bozuk komut dosyası davranışına neden olur.
Aşağıdaki bölümlerde bu davranışların her biri ve komut dosyası kodunuzu V8'e taşıma sırasında düzeltmek için uygulamanız gereken adımlar açıklanmaktadır.
Kaçınma: for each(variable in object)
for each (variable in object)
ifadesi JavaScript 1.6'ya eklenmiş ve for...of
yerine kaldırılmıştır.
Komut dosyanızı V8'e taşırken for each (variable in object)
ifadeleri kullanmaktan kaçının.
Bunun yerine for (variable in object)
kullanın:
// 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); } |
Kaçınma: Date.prototype.getYear()
Orijinal Rhino çalışma zamanında Date.prototype.getYear()
, 1900-1999 arasındaki yıllar için iki basamaklı yıllar değerini, diğer tarihler için ise dört basamaklı yıl değerini döndürür. Bu, JavaScript 1.2 ve önceki sürümlerde olduğu gibidir.
V8 çalışma zamanında, Date.prototype.getYear()
ECMAScript standartlarının gerektirdiği şekilde yıl eksi 1900 değerini döndürür.
Komut dosyanızı V8'e taşırken daima Date.prototype.getFullYear()
kullanın. Bu işlem, tarihten bağımsız olarak dört haneli bir yıl döndürür.
Ayrılmış anahtar kelimeleri ad olarak kullanmaktan kaçının
ECMAScript, işlev ve değişken adlarında belirli ayrılmış anahtar kelimelerin kullanılmasına izin vermez. Rhino çalışma zamanı bu kelimelerin birçoğuna izin verir. Bu nedenle, kodunuz bunları kullanıyorsa işlevlerinizi veya değişkenlerinizi yeniden adlandırmanız gerekir.
Komut dosyanızı V8'e taşırken değişkeni veya işlevleri ayrılmış anahtar kelimelerden birini kullanarak adlandırmayın.
Anahtar kelime adını kullanmaktan kaçınmak için değişkenleri veya işlevleri yeniden adlandırın. Anahtar kelimelerin ad olarak yaygın kullanımları class
, import
ve export
'dir.
const
değişkeni yeniden atamaktan kaçının
Orijinal Rhino çalışma zamanında, const
kullanarak bir değişken bildirebilirsiniz. Bu, simgenin değerinin hiçbir zaman değişmediği ve sembole gelecekte yapılacak atamaların yok sayıldığı anlamına gelir.
Yeni V8 çalışma zamanında, const
anahtar kelimesi standartla uyumludur ve const
olarak tanımlanan bir değişkene atanması, TypeError: Assignment to constant variable
çalışma zamanı hatasıyla sonuçlanır.
Komut dosyanızı V8'e taşırken const
değişkeninin değerini yeniden atamaya çalışmayın:
// 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 değişmez değerlerinden ve XML nesnesinden kaçının
ECMAScript'e yapılan bu standart olmayan uzantı, Apps Komut Dosyası projelerinin doğrudan XML söz dizimini kullanmasına olanak tanır.
Komut dosyanızı V8'e taşırken doğrudan XML değişmez değerlerini veya XML nesnesini kullanmaktan kaçının.
Bunun yerine XML'yi ayrıştırmak için XmlService'i kullanın:
// 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__
kullanarak özel yineleyici işlevleri oluşturmayın
JavaScript 1.7, herhangi bir sınıfın prototipinde bir __iterator__
işlevi tanımlayarak herhangi bir klas öğesine özel yineleyici eklenmesine olanak tanıyan bir özellik ekledi. Bu işlev, geliştiricilere kolaylık sağlamak için Apps Komut Dosyası'nın Rhino çalışma zamanına da eklendi. Ancak bu özellik hiçbir zaman ECMA-262 standardının bir parçası değildir ve ECMAScript uyumlu JavaScript motorlarında kaldırılmıştır. V8 kullanan komut dosyaları,
bu yineleme yapısını kullanamaz.
Komut dosyanızı V8'e taşırken özel yineleyiciler oluşturmak için __iterator__
işlevinden kaçının. Bunun yerine ECMAScript 6 yinelemelerini kullanın.
Aşağıdaki dizi yapısını göz önünde bulundurun:
// 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. |
Aşağıdaki kod örnekleri, Rhino çalışma zamanında bir iterasyonun nasıl oluşturulabileceğini ve V8 çalışma zamanında bir yedek yinelemenin nasıl oluşturulacağını gösterir:
// 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); } |
Koşullu yakalama yan tümcelerinden kaçınma
V8 çalışma zamanı, standartla uyumlu olmadıkları için catch..if
koşullu yakalama yan tümcelerini desteklemez.
Komut dosyanızı V8'e taşırken yakalama koşullarını yakalama gövdesindeki taşıyın:
// 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()
kullanmaktan kaçının
JavaScript 1.3, hiçbir ECMAScript standardının parçası olmayan bir Object.prototype.toSource() yöntemi içeriyordu. V8 çalışma zamanında desteklenmez.
Komut dosyanızı V8'e taşırken tüm Object.prototype.toSource() kullanımını kodunuzdan kaldırın.
Diğer farklar
Komut dosyası hatalarına neden olabilecek yukarıdaki uyumsuzluklara ek olarak, düzeltilmemesi halinde beklenmedik V8 çalışma zamanı komut dosyası davranışına neden olabilecek birkaç farklılık daha vardır.
Aşağıdaki bölümlerde, bu beklenmedik sürprizleri önlemek için komut dosyası kodunuzu nasıl güncelleyeceğiniz açıklanmaktadır.
Yerel ayara özel tarih ve saat biçimlendirmesini ayarla
Date
toLocaleString()
, toLocaleDateString()
ve toLocaleTimeString()
yöntemleri Rhino'ya kıyasla V8 çalışma zamanında farklı şekilde davranır.
Rhino'da varsayılan biçim uzun biçimdir ve aktarılan tüm parametreler ignoreed (yoksayılır) biçimindedir.
V8 çalışma zamanında varsayılan biçim kısa biçimdir ve aktarılan parametreler ECMA standardına göre işlenir (ayrıntılar için toLocaleDateString()
belgelerine bakın).
Komut dosyanızı V8'e taşırken, yerel ayara özel tarih ve saat yöntemlerinin çıktısıyla ilgili olarak kodunuzun beklentilerini test edin ve ayarlayın:
// 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
ve Error.lineNumber
kullanmaktan kaçının
V8 zaman aşımında, standart JavaScript Error
nesnesi, oluşturucu parametreleri veya nesne özellikleri olarak fileName
ya da lineNumber
öğelerini desteklemez.
Komut dosyanızı V8'e taşırken Error.fileName
ve Error.lineNumber
üzerindeki tüm bağımlılıkları kaldırın.
Alternatif olarak, Error.prototype.stack
kullanılabilir.
Bu yığın da standart değildir, ancak hem Rhino hem de V8'de desteklenir. İki platform tarafından oluşturulan yığın izlemenin biçimi biraz farklıdır:
// 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) |
Dizeleştirilmiş enum nesnelerinin işlenmesini ayarlama
Orijinal Rhino çalışma zamanında, bir enum nesnesinde JavaScript JSON.stringify()
yöntemini kullanmak yalnızca {}
değerini döndürür.
V8'de, bir enum nesnesinde aynı yöntemin kullanılması enum adını yeniden döndürür.
Komut dosyanızı V8'e taşırken kodunuzun enum nesnelerinin çıktısıyla ilgili JSON.stringify()
beklentilerini test edin ve ayarlayın:
// 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" |
Tanımlanmamış parametrelerin işlenmesini ayarla
Orijinal Rhino çalışma zamanında, undefined
parametresini bir yönteme geçirmek, "undefined"
dizesinin bu yönteme geçirilmesiyle sonuçlanır.
V8'de undefined
yöntemlerinin geçirilmesi, null
öğesinin geçirilmesiyle eşdeğerdir.
Komut dosyanızı V8'e taşırken kodunuzun undefined
parametreleriyle ilgili beklentilerini test edin ve ayarlayın:
// 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. |
Genel this
öğesinin kullanımını ayarlayın
Rhino çalışma zamanı, onu kullanan komut dosyaları için dolaylı bir özel bağlam tanımlar.
Komut dosyası kodu, gerçek genel this
değerinden farklı olarak bu dolaylı bağlamda çalışır. Bu, koddaki "genel this
" referanslarının, yalnızca komut dosyasında tanımlanan kodu ve değişkenleri içeren özel bağlamı değerlendirdiği anlamına gelir. Yerleşik Apps Komut Dosyası hizmetleri ve ECMAScript nesneleri, bu this
kullanımından hariç tutulur. Bu durum şu JavaScript yapısına
benzerdi:
// 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'de örtülü özel bağlam kaldırılır. Komut dosyasında tanımlanan genel değişkenler ve işlevler, yerleşik Apps Komut Dosyası hizmetlerinin ve Math
ile Date
gibi yerleşik ECMAScript öğelerinin yanına, genel bağlamda yerleştirilir.
Komut dosyanızı V8'e taşırken kodunuzun küresel bağlamda this
kullanımıyla ilgili beklentilerini test edin ve ayarlayın. Çoğu durumda, farklar yalnızca kodunuz genel this
nesnesinin anahtarlarını veya özellik adlarını incelerse görünür:
// 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)); } |
Kitaplıklarda instanceof
öğesinin işlenmesini ayarlayın
Kitaplıkta, başka bir projedeki bir işlevde parametre olarak geçirilen nesnedeki instanceof
kullanımı yanlış negatif verebilir. V8 çalışma zamanında bir proje ve kitaplıkları, farklı yürütme bağlamlarında çalıştırılır ve bu nedenle farklı genel ve prototip zincirleri olur.
Bu durumun, yalnızca kitaplığınızda instanceof
projesinin projenizde oluşturulmamış bir nesnede kullanılması durumunda geçerli olduğunu unutmayın. Bu anahtar kelimeyi projenizin içinde oluşturulan bir nesne üzerinde, projenizin içindeki aynı veya farklı bir komut dosyasında kullanmak beklendiği gibi işlemelidir.
V8'de çalışan bir proje, komut dosyanızı kitaplık olarak kullanıyorsa komut dosyanızın başka bir projeden aktarılacak bir parametrede instanceof
kullanıp kullanmadığını kontrol edin. instanceof
kullanımını ayarlayın ve kullanım alanınıza göre diğer uygun alternatifleri kullanın.
a instanceof b
için bir alternatif, prototip zincirinin tamamında arama yapmanız ve yalnızca oluşturucuyu kontrol etmeniz gerekmediği durumlarda a
oluşturucuyu kullanmak olabilir.
Kullanım: a.constructor.name == "b"
A Projesinin ve B Projesinin kütüphane olarak kullandığı proje A'yı düşünün.
//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 } |
Başka bir alternatif de ana projede instanceof
işlevini kontrol eden bir işlev sunmak ve bir kitaplık işlevini çağırırken bu işlevi diğer parametrelere ek olarak iletmek olabilir. İletilen işlev daha sonra kitaplık içinde instanceof
işlevini kontrol etmek için kullanılabilir.
//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); } |
Paylaşılmayan kaynakların kitaplıklara iletilmesini ayarla
Paylaşılmayan bir kaynağın ana komut dosyasından kitaplığa geçirilmesi, V8 çalışma zamanında farklı şekilde çalışır.
Rhino çalışma zamanında, paylaşılmayan bir kaynağın aktarılması işe yaramaz. Kitaplık bunun yerine kendi kaynağını kullanır.
V8 çalışma zamanında, paylaşılmayan bir kaynağı kitaplığa iletmek işe yarar. Kitaplık, iletilen paylaşılmayan kaynağı kullanır.
Paylaşılmayan kaynakları işlev parametreleri olarak iletmeyin. Paylaşılmayan kaynakları, her zaman onları kullanan komut dosyasında bildirin.
A Projesinin ve B Projesinin kütüphane olarak kullandığı proje A'yı düşünün. Bu örnekte PropertiesService
paylaşılmayan bir kaynaktır.
// Rhino runtime // Project A function testPassingNonSharedProperties() { PropertiesService.getScriptProperties() .setProperty('project', 'Project-A'); B.setScriptProperties(); // Prints: Project-B Logger.log(B.getScriptProperties( PropertiesService, 'project')); } |
// V8 runtime // Project A function testPassingNonSharedProperties() { PropertiesService.getScriptProperties() .setProperty('project', 'Project-A'); B.setScriptProperties(); // Prints: Project-A Logger.log(B.getScriptProperties( PropertiesService, 'project')); } |
Bağımsız komut dosyalarına erişimi güncelleme
V8 çalışma zamanında çalışan bağımsız komut dosyalarında, komut dosyası tetikleyicilerinin düzgün çalışması için kullanıcılara en azından komut dosyasına görüntüleme erişimi sağlamanız gerekir.