Apakah mungkin untuk memperluas kelas di ES6 tanpa memanggil super
metode untuk memanggil kelas induk?
EDIT: Pertanyaannya mungkin menyesatkan. Apakah ini standar yang harus kita panggil super()
atau apakah saya melewatkan sesuatu?
Sebagai contoh:
class Character {
constructor(){
console.log('invoke character');
}
}
class Hero extends Character{
constructor(){
super(); // exception thrown here when not called
console.log('invoke hero');
}
}
var hero = new Hero();
Ketika saya tidak memanggil super()
kelas turunan, saya mendapatkan masalah lingkup ->this is not defined
Saya menjalankan ini dengan iojs --harmony di v2.3.0
javascript
class
inheritance
ecmascript-6
xhallix.dll
sumber
sumber
Jawaban:
Aturan untuk kelas ES2015 (ES6) pada dasarnya adalah:
this
tidak dapat digunakan sampaisuper
dipanggil.super
jika mereka adalah subkelas, atau mereka harus secara eksplisit mengembalikan beberapa objek untuk menggantikan objek yang tidak diinisialisasi.Ini tergantung pada dua bagian penting dari spesifikasi ES2015.
Bagian 8.1.1.3.4 mendefinisikan logika untuk memutuskan apa yang
this
ada di dalam fungsi. Bagian penting untuk kelas adalah dimungkinkan untukthis
berada dalam"uninitialized"
keadaan, dan ketika dalam keadaan ini, mencoba menggunakanthis
akan memunculkan pengecualian.Bagian 9.2.2 ,
[[Construct]]
yang mendefinisikan perilaku fungsi yang dipanggil melaluinew
atausuper
. Saat memanggil konstruktor kelas dasar,this
diinisialisasi pada langkah # 8[[Construct]]
, tetapi untuk semua kasus lainnya,this
tidak diinisialisasi. Pada akhir konstruksi,GetThisBinding
dipanggil, jadi jikasuper
belum dipanggil (dengan demikian menginisialisasithis
), atau objek pengganti eksplisit tidak dikembalikan, baris terakhir dari panggilan konstruktor akan memunculkan pengecualian.sumber
super()
?super()
konstruktor?return Object.create(new.target.prototype, …)
untuk menghindari pemanggilan konstruktor super.Ada banyak jawaban dan komentar yang menyatakan bahwa
super
HARUS menjadi baris pertama di dalamnyaconstructor
. Itu salah. @loganfsmyth jawaban memiliki referensi persyaratan yang diperlukan, tetapi intinya adalah:extends
Konstruktor Inheriting ( ) harus memanggilsuper
sebelum menggunakanthis
dan sebelum kembali bahkan jikathis
tidak digunakanLihat fragmen di bawah (berfungsi di Chrome ...) untuk mengetahui mengapa masuk akal untuk memiliki pernyataan (tanpa menggunakan
this
) sebelum memanggilsuper
.sumber
"See fragment below (works in Chrome...)"
membuka konsol pengembang krom dan klik pada "kode Run potongan":Uncaught ReferenceError: this is not defined
. Tentu, Anda dapat menggunakan metode dalam konstruktor sebelumnya,super()
tetapi Anda tidak dapat menggunakan metode dari kelas sebelumnya!this
sebelumnyasuper()
(kode Anda membuktikannya) tidak ada hubungannya dengan spesifikasi secara langsung, tetapi dengan implementasi javascript. Jadi, Anda harus memanggil 'super' sebelum 'ini'.super
, dan Anda menyatakan bahwa penggunaanthis
sebelum menelepon adalah ilegalsuper
. Kami berdua benar, hanya tidak memahami satu sama lain :-) (Dan pengecualian itu disengaja, untuk menunjukkan apa yang tidak legal - saya bahkan menamai properti itu 'WillFail')Sintaks kelas es6 baru hanyalah notasi lain untuk "lama" kelas "es5" dengan prototipe. Oleh karena itu, Anda tidak dapat membuat instance kelas tertentu tanpa menyetel prototipe-nya (kelas dasar).
Itu seperti meletakkan keju di atas sandwich Anda tanpa membuatnya. Juga Anda tidak bisa menaruh keju sebelum membuat sandwich, jadi ...
... menggunakan
this
kata kunci sebelum memanggil kelas super dengansuper()
juga tidak diperbolehkan.Jika Anda tidak menentukan konstruktor untuk kelas dasar, definisi berikut digunakan:
Untuk kelas turunan, konstruktor default berikut digunakan:
EDIT: Temukan ini di
developer.mozilla.org
:Sumber
sumber
this
tidak digunakan sama sekali. 2. JS bukan sandwich, dan di ES5 Anda selalu dapat menggunakannyathis
, bahkan sebelum memanggil fungsi lain yang Anda suka (yang mungkin atau mungkin tidak mendefinisikan properti suplemen)this
juga ?! 2. Kelas JS saya mewakili sandwich, dan di ES6 Anda tidak selalu bisa menggunakannyathis
. Saya hanya mencoba menjelaskan kelas es6 (dengan metafora), dan tidak ada yang membutuhkan komentar yang merusak / tidak perlu.Baru saja mendaftar untuk memposting solusi ini karena jawaban di sini sama sekali tidak memuaskan saya karena sebenarnya ada cara sederhana untuk melakukannya. Sesuaikan pola pembuatan kelas Anda untuk menimpa logika Anda dalam sub-metode saat hanya menggunakan konstruktor super dan meneruskan argumen konstruktor ke sana.
Seperti halnya Anda, jangan membuat konstruktor di subkelas Anda sendiri tetapi hanya merujuk ke metode yang diganti di subkelas masing-masing.
Itu berarti Anda membebaskan diri dari fungsionalitas konstruktor yang diberlakukan pada Anda dan menahan diri ke metode biasa - yang dapat diganti dan tidak menerapkan super () setelah Anda membiarkan diri Anda memilih jika, di mana, dan bagaimana Anda ingin memanggil super (sepenuhnya opsional) misalnya:
Bersulang!
sumber
Anda bisa menghilangkan super () di subclass Anda, jika Anda menghilangkan konstruktor sama sekali di subclass Anda. Konstruktor default 'tersembunyi' akan disertakan secara otomatis dalam subkelas Anda. Namun, jika Anda menyertakan konstruktor dalam subkelas Anda, super () harus dipanggil dalam konstruktor itu.
Baca ini untuk informasi lebih lanjut.
sumber
Jawaban dengan justyourimage adalah cara termudah, tetapi contohnya sedikit membengkak. Berikut versi generiknya:
Jangan memperpanjang yang asli
constructor()
, cukup gunakan yang palsu_constructor()
untuk logika instantiation.Catatan, solusi ini membuat proses debug mengganggu karena Anda harus menggunakan metode tambahan untuk setiap pembuatan instance.
sumber
Mencoba:
Demo
sumber
A constructor *can* use the super keyword to call the constructor of a parent class.
jadi saya akan mengatakan menunggu rilis ES6Saya akan merekomendasikan untuk menggunakan OODK-JS jika Anda ingin mengembangkan konsep OOP berikut.
sumber
Solusi sederhana: Saya rasa sudah jelas tidak perlu penjelasan.
sumber
@Bergi disebutkan
new.target.prototype
, tetapi saya sedang mencari contoh konkret yang membuktikan bahwa Anda dapat mengaksesthis
(atau lebih baik, referensi ke objek yang dibuat dengan kode kliennew
, lihat di bawah) tanpa harus meneleponsuper()
sama sekali.Bicara itu murah, tunjukkan kodenya ... Jadi ini contohnya:
Yang akan menghasilkan:
Jadi Anda dapat melihat bahwa kita secara efektif membuat objek bertipe
B
(kelas anak) yang juga merupakan objek bertipeA
(kelas induknya) dan di dalamchildMethod()
anakB
kita telahthis
menunjuk ke objekobj
yang kita buat di B'sconstructor
withObject.create(new.target.prototype)
.Dan semua ini tanpa peduli
super
sama sekali.Ini memanfaatkan fakta bahwa di JS a
constructor
dapat mengembalikan objek yang sama sekali berbeda ketika kode klien membuat instance baru dengannew
.Semoga ini bisa membantu seseorang.
sumber