Dalam pertanyaan lain , pengguna menunjukkan bahwa new
kata kunci berbahaya untuk digunakan dan mengusulkan solusi untuk pembuatan objek yang tidak digunakan new
. Saya tidak percaya itu benar, sebagian besar karena saya telah menggunakan Prototipe, Scriptaculous dan pustaka JavaScript yang sangat baik lainnya, dan semua orang dari mereka menggunakan new
kata kunci.
Terlepas dari itu, kemarin saya menonton pembicaraan Douglas Crockford di teater YUI dan dia mengatakan hal yang persis sama, bahwa dia tidak menggunakan new
kata kunci lagi dalam kodenya ( Crockford pada JavaScript - Act III: Function the Ultimate - 50:23 menit ).
Apakah 'buruk' menggunakan new
kata kunci? Apa kelebihan dan kekurangan dari menggunakannya?
javascript
Pablo Fernandez
sumber
sumber
new
. Tetapi ketika Anda melihat perpustakaan YUI. Anda harus menggunakannya dinew
mana-mana. Sepertivar myDataSource = new Y.DataSource.IO({source:"./myScript.php"});
.init
metode jika Anda menggunakanObject.create
pendekatan dan memanggilnya setelah itu. Jauh lebih mudah untuk hanya menggunakannew
keduanya, mengatur rantai prototipe dan memanggil beberapa kode penginisialisasi.new
tidak berbahaya. Menghilangkannew
itu berbahaya, dan karena itu buruk . Tetapi dalam ES5 Anda dapat menggunakan Mode Ketat , yang melindungi Anda dari bahaya itu dan banyak lainnya.Jawaban:
Crockford telah melakukan banyak hal untuk mempopulerkan teknik JavaScript yang baik. Pendiriannya yang tegas tentang unsur-unsur utama bahasa telah memicu banyak diskusi bermanfaat. Yang mengatakan, ada terlalu banyak orang yang menganggap setiap proklamasi "buruk" atau "berbahaya" sebagai Injil, menolak untuk melihat melampaui pendapat satu orang. Kadang-kadang bisa sedikit frustasi.
Penggunaan fungsi yang disediakan oleh
new
kata kunci memiliki beberapa keunggulan dibandingkan membangun setiap objek dari awal:prototype
dan digunakannew
untuk membasmi objek baru. Tidak hanya ini lebih cepat (tidak ada kode yang diperlukan untuk masing-masing dan setiap metode pada prototipe), itu menghindari membengkak setiap objek dengan properti terpisah untuk setiap metode. Pada mesin yang lebih lambat (atau terutama, lebih lambat JS interpreter) ketika banyak objek sedang dibuat ini dapat berarti penghematan yang signifikan dalam waktu dan memori.Dan ya,
new
memiliki satu kelemahan penting, dengan cakap dijelaskan oleh jawaban lain: jika Anda lupa menggunakannya, kode Anda akan rusak tanpa peringatan. Untungnya, kerugian itu mudah dikurangi - cukup tambahkan sedikit kode ke fungsi itu sendiri:Sekarang Anda dapat memiliki keuntungan
new
tanpa harus khawatir tentang masalah yang disebabkan oleh penyalahgunaan yang tidak disengaja. Anda bahkan bisa menambahkan pernyataan ke cek jika pikiran kode yang rusak diam-diam mengganggu Anda. Atau, seperti dikomentari beberapa orang , gunakan tanda centang untuk memperkenalkan pengecualian runtime:(Perhatikan bahwa cuplikan ini dapat menghindari pengkodean nama fungsi konstruktor, karena tidak seperti contoh sebelumnya ia tidak perlu benar-benar instantiate objek - oleh karena itu, ia dapat disalin ke setiap fungsi target tanpa modifikasi.)
John Resig merinci teknik ini di pos Instansiasi "Kelas" -nya yang Sederhana , serta memasukkan cara untuk membangun perilaku ini ke dalam "kelas" Anda secara default. Pasti layak dibaca ... seperti buku terbarunya, Rahasia Ninja JavaScript , yang menemukan tersembunyi emas dalam hal ini dan banyak lainnya "berbahaya" fitur bahasa JavaScript (yang bab tentang
with
terutama mencerahkan bagi kita yang awalnya diberhentikan fitur yang banyak difitnah ini sebagai gimmick).sumber
new
, atau gunakan fungsi pembungkus untuk mengingatnya untuk Anda. Saya menduga bahwa jika Anda berada pada titik di mana itu penting, Anda sudah kehabisan optimasi lainnya seperti memoisasi, jadi panggilan kreasi Anda akan dilokalkan ...arguments.callee
untuk memeriksa apakah Anda telah dipanggil dengannew
mungkin tidak begitu baik, karenaarguments.callee
tidak tersedia dalam mode ketat. Lebih baik menggunakan nama fungsi.new
karena Anda bisa lupa menuliskannya dalam kode Anda sama konyolnya dengan contoh saya.Saya baru saja membaca beberapa bagian dari bukunya Crockfords "Javascript: The Good Parts". Saya merasa bahwa dia menganggap segala sesuatu yang pernah menggigitnya berbahaya:
Tentang sakelar jatuh:
Tentang ++ dan -
Tentang baru:
Ada lebih banyak, tetapi saya harap Anda mendapatkan gambarannya.
Jawaban saya untuk pertanyaan Anda: Tidak, itu tidak berbahaya. tetapi jika Anda lupa menggunakannya ketika Anda harusnya Anda bisa memiliki beberapa masalah. Jika Anda berkembang di lingkungan yang baik Anda perhatikan itu.
Memperbarui
Sekitar setahun setelah jawaban ini ditulis ECMAScript edisi ke-5 dirilis, dengan dukungan untuk mode ketat . Dalam mode ketat,
this
tidak lagi terikat ke objek global tetapi keundefined
.sumber
Javascript menjadi bahasa yang dinamis ada banyak cara untuk mengacaukan di mana bahasa lain akan menghentikan Anda.
Menghindari fitur bahasa mendasar seperti
new
pada dasar bahwa Anda mungkin mengacaukan adalah seperti melepas sepatu baru Anda yang mengkilap sebelum berjalan melalui ladang ranjau untuk berjaga-jaga jika Anda mungkin membuat sepatu Anda becek.Saya menggunakan konvensi di mana nama fungsi dimulai dengan huruf kecil dan 'fungsi' yang sebenarnya definisi kelas dimulai dengan huruf besar. Hasilnya adalah petunjuk visual yang benar-benar sangat meyakinkan bahwa 'sintaks' salah: -
Selain itu, kebiasaan pemberian nama yang baik ini membantu. Setelah semua fungsi melakukan hal-hal dan oleh karena itu harus ada kata kerja dalam namanya sedangkan kelas mewakili objek dan kata benda dan kata sifat tanpa kata kerja.
Sangat menarik bagaimana pewarnaan sintaks SO telah menafsirkan kode di atas.
sumber
if (! this instanceof MyClass) return new MyClass()
) saya sebenarnya lebih sukanew
sintaks -less. Mengapa? Karena fungsi lebih umum daripada fungsi konstruktor . Meninggalkannew
membuatnya mudah untuk mengubah fungsi konstruktor menjadi fungsi biasa ... Atau sebaliknya. Menambahkan menambahkannew
membuat kode lebih spesifik daripada yang seharusnya. Dan karenanya kurang fleksibel. Bandingkan dengan Java yang direkomendasikan untuk menerimaList
alih-alihArrayList
agar penelepon dapat memilih implementasinya.Saya pemula untuk Javascript jadi mungkin saya tidak terlalu berpengalaman dalam memberikan sudut pandang yang baik untuk ini. Namun saya ingin membagikan pandangan saya tentang hal "baru" ini.
Saya berasal dari dunia C # di mana menggunakan kata kunci "baru" begitu alami sehingga pola desain pabrik yang terlihat aneh bagi saya.
Ketika saya pertama kali kode dalam Javascript, saya tidak menyadari bahwa ada kata kunci dan kode "baru" seperti yang ada dalam pola YUI dan tidak butuh waktu lama bagi saya untuk mengalami bencana. Saya kehilangan jejak apa yang seharusnya dilakukan baris tertentu ketika melihat kembali kode yang saya tulis. Lebih kacau adalah bahwa pikiran saya tidak bisa benar-benar transit antara batas-batas instance objek ketika saya "kering-menjalankan" kode.
Kemudian, saya menemukan kata kunci "baru" yang bagi saya, itu "memisahkan" hal-hal. Dengan kata kunci baru, itu menciptakan sesuatu. Tanpa kata kunci baru, saya tahu saya tidak akan bingung dengan menciptakan sesuatu kecuali fungsi yang saya panggil memberi saya petunjuk kuat tentang itu.
Misalnya, dengan
var bar=foo();
saya tidak memiliki petunjuk sebagai bilah apa yang mungkin .... Apakah ini nilai balik atau apakah itu objek yang baru dibuat? Tetapi denganvar bar = new foo();
saya tahu pasti bar adalah sebuah objek.sumber
typeof new foo() == "object"
. Itu yangnew
mengembalikan instance darifoo
, dan Anda tahu Anda bisa meneleponfoo.bar()
danfoo.bang()
. Namun itu dapat dengan mudah dikurangi dengan menggunakan JsDoc's @return Bukannya saya mengadvokasi untuk kode prosedural (menghindari katanew
)Kasus lain untuk yang baru adalah apa yang saya sebut Pooh Coding . Winnie the Pooh mengikuti perutnya. Saya katakan pergi dengan bahasa yang Anda gunakan, bukan menentangnya .
Kemungkinannya adalah pengelola bahasa akan mengoptimalkan bahasa untuk idiom yang mereka coba dorong. Jika mereka memasukkan kata kunci baru ke dalam bahasa, mereka mungkin berpikir masuk akal untuk menjelaskan ketika membuat contoh baru.
Kode yang ditulis mengikuti niat bahasa akan meningkat efisiensi dengan setiap rilis. Dan kode menghindari konstruksi utama bahasa akan menderita seiring waktu.
EDIT: Dan ini melampaui kinerja. Saya tidak dapat menghitung berapa kali saya mendengar (atau berkata) "mengapa mereka melakukan itu ?" ketika menemukan kode yang terlihat aneh. Sering kali ternyata pada saat kode itu ditulis ada alasan "bagus" untuk itu. Mengikuti Tao bahasa adalah asuransi terbaik Anda karena tidak ada kode Anda diejek beberapa tahun dari sekarang.
sumber
Saya menulis posting tentang cara mengurangi masalah memanggil konstruktor tanpa kata kunci baru.
Sebagian besar didaktik, tetapi ini menunjukkan bagaimana Anda dapat membuat konstruktor yang bekerja dengan atau tanpa
new
dan tidak mengharuskan Anda menambahkan kode boilerplate untuk diujithis
di setiap konstruktor.http://js-bits.blogspot.com/2010/08/constructors-without-using-new.html
Inilah inti dari teknik ini:
Berikut cara menggunakannya:
sumber
arguments.callee
luar biasa!surrogateConstructor
seharusnyasurrogateCtor
(atau sebaliknya).Alasan di balik tidak menggunakan kata kunci baru, sederhana:
Dengan tidak menggunakannya sama sekali, Anda menghindari jebakan yang datang dengan menghilangkannya secara tidak sengaja. Pola konstruksi yang digunakan YUI, adalah contoh bagaimana Anda dapat menghindari kata kunci baru sama sekali "
Atau Anda bisa melakukannya:
Tapi dengan demikian Anda menjalankan risiko seseorang lupa untuk menggunakan baru kata kunci, dan ini operator yang menjadi semua fubar. AFAIK tidak ada untungnya melakukan ini (selain Anda sudah terbiasa).
Pada Akhir Hari: Ini tentang bersikap defensif. Bisakah Anda menggunakan pernyataan baru? Iya. Apakah itu membuat kode Anda lebih berbahaya? Iya.
Jika Anda pernah menulis C ++, ini mirip dengan mengatur pointer ke NULL setelah Anda menghapusnya.
sumber
Saya pikir "baru" menambah kejelasan kode. Dan kejelasan itu layak untuk semuanya. Senang mengetahui ada jebakan, tetapi menghindarinya dengan menghindari kejelasan sepertinya bukan jalan bagi saya.
sumber
Kasus 1:
new
tidak diperlukan dan harus dihindariWadah 2:
new
wajib diisi, jika tidak Anda akan mendapatkan kesalahansumber
toString()
). Dalam semua kasus lain, gunakan literal. BukanString('asd')
, tapi sederhana'asd'
, dan tidakNumber(12)
, tapi sederhana12
.Array
:Array(5).fill(0)
jelas lebih mudah dibaca daripada[undefined, undefined, undefined, undefined, undefined].fill(0)
dan(var arr = []).length = 5; arr.fill(0);
new
dengan konstruktor untuk tipe objek yang sesuai dengan tipe primitif . Literal yang Anda sarankan tidak setara denganArray
panggilan (coba0 in …
), dan sisanya adalah kesalahan sintaks :) Kalau tidak Anda benar, meskipun harus dicatat juga yangArray(5)
bisa ambigu jika Anda mempertimbangkan implementasi yang tidak sesuai (dan karena itu ditiruArray.prototype.fill(…)
).Berikut ini ringkasan singkat yang bisa saya sampaikan dari dua argumen terkuat untuk dan menentang penggunaan
new
operator:Argumen menentang
new
new
operator dapat memiliki efek bencana jika mereka salah dipanggil sebagai fungsi normal. Kode fungsi dalam kasus seperti itu akan dieksekusi dalam lingkup tempat fungsi dipanggil, alih-alih dalam lingkup objek lokal sebagaimana dimaksud. Ini dapat menyebabkan variabel dan properti global ditimpa dengan konsekuensi yang merusak.function Func()
, dan kemudian memanggilFunc.prototype
dan menambahkan barang-barang ke dalamnya sehingga Anda dapat meneleponnew Func()
untuk membangun objek Anda tampak jelek bagi beberapa programmer, yang lebih suka menggunakan gaya objek pewarisan lain untuk alasan arsitektur dan gaya.Untuk lebih lanjut tentang argumen ini, lihat buku Douglas Crockford yang hebat dan ringkas Javascript: The Good Parts. Bahkan periksa saja.
Argumen yang mendukung
new
new
operator dan penugasan prototypal cepat.Lihat posting John Resig untuk penjelasan sederhana tentang teknik ini, dan untuk penjelasan yang lebih dalam tentang model pewarisan yang ia dukung.
sumber
'use strict';
mode (atau metode di tautan Anda) # 2 Memiliki gula synatic dalam ES6 , namun perilakunya sama seperti sebelumnya.Saya setuju dengan pez dan beberapa di sini.
Tampak jelas bagi saya bahwa "baru" adalah penciptaan objek deskriptif diri, di mana pola YUI menggambarkan Greg Dean sepenuhnya dikaburkan .
Kemungkinan seseorang bisa menulis
var bar = foo;
atau divar bar = baz();
mana baz bukan metode membuat objek tampaknya jauh lebih berbahaya.sumber
Saya pikir baru itu jahat, bukan karena jika Anda lupa menggunakannya secara tidak sengaja mungkin akan menimbulkan masalah, tetapi karena itu merusak rantai warisan, membuat bahasa lebih sulit untuk dipahami.
JavaScript adalah berorientasi objek berbasis prototipe. Karenanya setiap objek HARUS dibuat dari objek lain seperti itu
var newObj=Object.create(oldObj)
. Di sini oldObj disebut prototipe newObj (karenanya "berbasis prototipe"). Ini menyiratkan bahwa jika sebuah properti tidak ditemukan di newObj maka itu akan dicari di oldObj . newObj secara default dengan demikian akan menjadi objek kosong tetapi karena rantai prototipe ini tampaknya memiliki semua nilai oldObj .Di sisi lain jika Anda melakukannya
var newObj=new oldObj()
, prototipe newObj adalah oldObj.prototype , yang tidak perlu sulit untuk dipahami.Triknya adalah menggunakan
Di dalam fungsi ini dan hanya di sini yang baru harus digunakan. Setelah ini cukup gunakan metode Object.create () . Metode ini menyelesaikan masalah prototipe.
sumber
var c = new Car()
sama dengan melakukanvar c = Object.create(Car.prototype); Car.call(c)