Önceki cevapları daha da genişletiyoruz ...
Genel bir derleyici bakış açısından ve sanal makineye özgü optimizasyonları göz ardı ederek:
İlk olarak, kodu belirteceğimiz sözcüksel analiz aşamasından geçiyoruz.
Örnek olarak, aşağıdaki belirteçler üretilebilir:
[]: ARRAY_INIT
[1]: ARRAY_INIT (NUMBER)
[1, foo]: ARRAY_INIT (NUMBER, IDENTIFIER)
new Array: NEW, IDENTIFIER
new Array(): NEW, IDENTIFIER, CALL
new Array(5): NEW, IDENTIFIER, CALL (NUMBER)
new Array(5,4): NEW, IDENTIFIER, CALL (NUMBER, NUMBER)
new Array(5, foo): NEW, IDENTIFIER, CALL (NUMBER, IDENTIFIER)
Umarım bu size yeterli bir görselleştirme sağlamalıdır, böylece daha fazla (veya daha az) işlemin ne kadar gerekli olduğunu anlayabilirsiniz.
Yukarıdaki belirteçlere dayanarak, ARRAY_INIT'in her zaman bir dizi üreteceğini biliyoruz. Bu nedenle basitçe bir dizi oluşturup onu dolduruyoruz. Belirsizliğe gelince, sözcük analizi aşaması, ARRAY_INIT'i bir nesne özelliği erişimcisinden (ör. obj[foo]
) Veya dizeler / normal ifade değişmezleri (ör. "Foo [] bar" veya / [] /) içindeki parantezlerden ayırmıştır.
Bu çok küçük ama aynı zamanda daha fazla tokenimiz var new Array
. Dahası, henüz bir dizi oluşturmak istediğimiz tam olarak belli değil. "Yeni" belirteci görüyoruz, ama "yeni" ne? Daha sonra, yeni bir "Dizi" istediğimizi belirten IDENTIFIER belirtecini görürüz, ancak JavaScript sanal makineleri genellikle "yerel global nesneler" için bir IDENTIFIER jetonu ve jetonları ayırt etmez. Bu nedenle ...
Bir IDENTIFIER belirteci ile her karşılaştığımızda kapsam zincirine bakmalıyız. Javascript VM'leri, "argümanlar" nesnesini, yerel olarak tanımlanmış değişkenleri vb. İçerebilen her yürütme bağlamı için bir "Aktivasyon nesnesi" içerir. Eğer onu Aktivasyon nesnesinde bulamazsak, genel kapsama ulaşana kadar kapsam zincirini aramaya başlarız. . Hiçbir şey bulunmazsa, bir ReferenceError
.
Değişken bildirimini bulduktan sonra, kurucuyu çağırırız. new Array
örtük bir işlev çağrısıdır ve temel kural, işlev çağrılarının yürütme sırasında daha yavaş olmasıdır (bu nedenle statik C / C ++ derleyicileri "işlev satır içi yapmaya" izin verir - SpiderMonkey gibi JS JIT motorlarının anında yapması gerekir)
Array
Yapıcı aşırı yüklü. Dizi yapıcısı yerel kod olarak uygulandığından bazı performans geliştirmeleri sağlar, ancak yine de bağımsız değişken uzunluğunu kontrol etmesi ve buna göre davranması gerekir. Dahası, yalnızca bir argüman sağlandığında, argümanın türünü daha fazla kontrol etmemiz gerekir. new Array ("foo") ["foo"] üretir, burada new Array (1) [undefined] üretir
Dolayısıyla, hepsini basitleştirmek için: dizi değişmezleriyle, VM bir dizi istediğimizi bilir; ile new Array
sanal makinenin new Array
gerçekte ne yaptığını anlamak için fazladan CPU döngüleri kullanması gerekir .