Memahami Spesifikasi Naskah ECMAS, Bagian 1



Selamat siang teman!

Pada artikel ini, kami mengambil fungsi dari spesifikasi dan menganalisis penjelasannya. Pergilah.

Kata pengantar


Bahkan jika Anda mengenal JavaScript dengan baik, membaca spesifikasinya bisa sulit. Kode berikut menunjukkan penggunaan Object.prototype.hasOwnProperty:

const o = {
    foo: 1
}
o.hasOwnProperty('foo') // true
o.hasOwnProperty('bar') // false

Dalam contoh, objek "o" tidak memiliki metode "hasOwnProperty", jadi kami merujuk ke prototipe - "Object.prototype" (rantai prototipe).

Untuk menjelaskan cara kerja Object.hasOwnProperty, spesifikasi menggunakan pseudocode berikut:

Object.prototype.hasOwnProperty (V)

Ketika hasOwnProperty dipanggil dengan argumen V, langkah-langkah berikut dilakukan: ... dan HasOwnProperty (O, P) Operasi abstrak HasOwnProperty digunakan untuk menentukan apakah objek memiliki properti sendiri dengan kunci tertentu. Nilai Boolean dikembalikan. Operasi ini disebut dengan argumen O dan P. Operasi ini terdiri dari langkah-langkah berikut: Apa itu "operasi abstrak"? Apa [[ ]]? Mengapa suatu fungsi memiliki tanda tanya? Apa yang dimaksud dengan "penegasan"? Ayo cari tahu.

  1. P ? ToPropertyKey(V)
  2. O ? ToObject( this)
  3. ? HasOwnProperty(O, P).







  1. (assert): Type(O) Object.
  2. : IsPropertyKey(P) true.
  3. desc ? O.[[GetOwnProperty]](P).
  4. desc undefined, false.
  5. true.





Jenis dalam bahasa dan jenis dalam spesifikasi


Mari kita mulai dengan sesuatu yang akrab. Dalam spesifikasi, ada nilai-nilai seperti tidak terdefinisi, benar dan salah, yang diketahui oleh kami oleh JS. Semuanya adalah "nilai bahasa" , "nilai jenis bahasa" , yang juga ditentukan oleh spesifikasi.

Spesifikasi menggunakan nilai-nilai bahasa bawaan, misalnya, tipe data internal dapat berisi bidang dengan nilai true atau false. Mesin JS umumnya tidak menggunakan makna linguistik dalam mekanisme internal mereka. Misalnya, jika mesin JS ditulis dalam C ++, kemungkinan besar akan menggunakan true dan false dari C ++, daripada representasi internal dari nilai Boolean dari JS.

Selain tipe bahasa, spesifikasi menggunakan tipe khusus (tipe spesifikasi) - tipe yang hanya digunakan dalam spesifikasi. Mesin JS tidak diperlukan untuk mengeksekusinya (tetapi mereka bisa). Pada artikel ini kita akan berkenalan dengan tipe khusus "Rekam" (catatan) dan subtipe "Catatan Penyelesaian" (catatan penyelesaian).

Operasi abstrak


Operasi abstrak adalah fungsi yang didefinisikan dalam spesifikasi; mereka didefinisikan untuk mengurangi spesifikasi. Mesin JS tidak diharuskan untuk menjalankannya sebagai fungsi yang berdiri sendiri. Di JS, mereka tidak bisa dipanggil secara langsung.

Slot internal dan metode internal


Slot internal dan metode internal ditunjukkan dengan nama yang terlampir dalam [[]].

Slot internal adalah elemen data (set) dari objek JS atau tipe khusus. Mereka digunakan untuk menyimpan informasi tentang keadaan objek. Metode internal adalah fungsi anggota dari objek JS.

Misalnya, setiap objek JS memiliki slot [[Prototipe]] internal dan metode [[GetOwnProperty]] internal.

Slot dan metode internal tidak tersedia di JS. Misalnya, kami tidak dapat mengakses o. [[Prototipe]] atau memanggil o. [[GetOwnProperty]] (). Mesin JS dapat mengeksekusi mereka untuk kebutuhan (internal) sendiri, tetapi tidak diharuskan untuk melakukan ini.

Kadang-kadang metode internal menjadi operasi abstrak dengan nama yang sama, seperti halnya dengan [[GetOwnProperty]]:

[[GetOwnProperty]] (P)

Ketika metode internal [[GetOwnProperty]] dari objek "O" dipanggil dengan kunci "P", tindakan berikut dilakukan: OrdinaryGetOwnProperty bukan metode internal, karena tidak terkait dengan objek apa pun; objek yang berfungsi diteruskan ke parameter. OrdinaryGetOwnProperty disebut "biasa" karena beroperasi pada objek biasa. Objek dalam ECMAScript biasa dan tidak biasa (eksotis). Suatu objek adalah biasa jika berperilaku dapat diprediksi dalam menanggapi serangkaian metode yang disebut metode internal esensial. Kalau tidak (ketika objek berperilaku tidak terduga; tidak seperti yang diharapkan; ketika perilaku objek menyimpang dari normal, menyimpang), itu dianggap tidak biasa.

  1. ! OrdinaryGetOwnProperty(O, P)





Objek tidak biasa yang paling terkenal adalah Array, karena properti "panjang" berperilaku tidak standar: pengaturan properti ini dapat menghapus elemen dari array.

Daftar metode internal dasar dapat ditemukan di sini .

Catatan penyelesaian


Bagaimana dengan tanda tanya dan tanda seru? Untuk memahami ini, Anda perlu memahami apa itu catatan penyelesaian .

Catatan penyelesaian adalah tipe khusus (hanya ditentukan untuk tujuan spesifikasi). Mesin JS tidak harus memiliki tipe data internal yang sama.

Catatan penyelesaian adalah tipe data yang memiliki set bidang bernama tetap. Catatan penyelesaian memiliki tiga bidang:
[[Tipe]]normal, break, continue, return throw. , normal, « () » (abrupt comlpetions)
[[Value]], , , , ,
[[Target]]( )

Setiap operasi abstrak secara implisit mengembalikan catatan penyelesaian. Bahkan jika hasil dari operasi abstrak adalah nilai logis sederhana, itu dibungkus dengan catatan penyelesaian tipe normal (lihat Nilai Penyelesaian Implisit ).

Catatan 1: spesifikasinya tidak terlalu konsisten di bagian ini; Ada beberapa fungsi pembantu yang mengembalikan nilai telanjang yang digunakan apa adanya, tanpa diambil dari catatan penyelesaian.

Catatan 2: Spesifikasi penulis berusaha membuat pemrosesan catatan penyelesaian lebih eksplisit.

Jika algoritme melempar pengecualian, itu berarti bahwa catatan penyelesaian akan diterima dengan lemparan tipe ([[Tipe]]) dan nilai ([[Nilai]])) sebagai objek pengecualian. Kami tidak akan mempertimbangkan jenis lain (istirahat, lanjutkan dan kembali) untuk saat ini.

ReturnIfAbrupt (argumen) berarti melakukan operasi berikut: Inilah catatan penyelesaiannya; jika berakhir tiba-tiba, segera kembali. Jika tidak, kami mengekstrak nilai dari catatan penyelesaian. ReturnIfAbrupt terlihat seperti pemanggilan fungsi, tetapi tidak. Kami memanggil fungsi yang mengembalikan ReturnIfAbrupt (), dan bukan ReturnIfAbrupt itu sendiri. Perilakunya lebih seperti makro dalam bahasa pemrograman mirip C. ReturnIfAbrupt dapat digunakan sebagai berikut: Di sini ikut bermain

  1. argument - (abrupt), argument.
  2. argument argument.[[Value]].







  1. obj Foo() (obj - ).
  2. ReturnIfAbrupt(obj).
  3. Bar(obj) ( , , obj - , ).

Tanda tanya : rekam  ? Foo () setara dengan ReturnIfAbrupt (Foo ()). Menggunakan singkatan ini memiliki nilai praktis: kita tidak perlu menulis kode penangan kesalahan setiap kali.

Dengan analogi, biarkan val menjadi entri ! Foo () setara dengan yang berikut: Menggunakan pengetahuan ini, kita dapat menulis ulang Object.prototype.hasOwnProperty sebagai berikut: Object.prototype.hasOwnProperty (P) ... HasOwnProperty dapat ditulis ulang seperti ini: HasOwnProperty (O, P) Kita juga dapat menulis ulang metode internal [ [GetOwnProperty]] tanpa tanda seru: O. [[GetOWnProperty]] Kami berasumsi bahwa temp adalah variabel sementara baru yang tidak berinteraksi dengan apa pun.

  1. val Foo().
  2. : val .
  3. val val.[[Value]].





  1. P ToProperty(V).
  2. P , P.
  3. P P.[[Value]].
  4. O ToObject( this).
  5. O , O.
  6. O O.[[Value]].
  7. temp HasOwnProperty(O, P).
  8. temp , temp.
  9. temp temp.[[Value]].
  10. NormalCompletion(temp).





  1. : Type(O) Object.
  2. : IsPropertyKey(P) true.
  3. desc O.[[GetOWnProperty]](P).
  4. desc , desc.
  5. desc desc.[[Value]].
  6. desc undefined, NormalCompletion(false).
  7. NormalCompletion(true).





  1. temp OrdinaryGetOwnProperty(O, P).
  2. : temp .
  3. temp temp.[[Value]].
  4. NormalCompletion(temp).



Kita juga tahu bahwa dalam kasus ketika pernyataan pengembalian mengembalikan sesuatu selain dari catatan penyelesaian, ini sesuatu yang secara implisit membungkus di NormalCompletion.

Fallback: Kembali? Foo ()


Apakah spesifikasinya menggunakan Return? Foo () - mengapa ada tanda tanya di sini?

Rekam Kembali? Foo () dapat diperluas sebagai berikut: Perilaku pengembalian ? Foo () sama untuk pengakhiran normal dan tiba-tiba. Rekam Kembali? Foo () memungkinkan Anda untuk lebih jelas menunjukkan bahwa Foo mengembalikan catatan penyelesaian.

  1. temp Foo().
  2. temp , temp.
  3. temp temp.[[Value]].
  4. NormalCompletion.





Pernyataan


Pernyataan dalam spesifikasi “menegaskan” kondisi invarian dari algoritma. Mereka ditambahkan ke spesifikasi untuk kejelasan, tetapi tidak mengandung persyaratan implementasi, oleh karena itu, mereka tidak perlu diverifikasi oleh implementasi spesifik.

Apa berikutnya?


Kami belajar membaca spesifikasi untuk metode sederhana seperti Object.prototype.hasOwnProperty dan operasi abstrak seperti HasOwnProperty. Dengan pengetahuan ini, kita dapat memahami apa yang dilakukan operasi abstrak lainnya, yang akan dibahas pada bagian selanjutnya. Juga di artikel berikutnya, kita akan melihat Penjelas Properti, yang merupakan jenis khusus lain.


Terima kasih atas perhatian Anda. Selamat coding!

All Articles