Komentar Alan Storm sebagai jawaban atas jawaban saya tentangwith
pernyataan itu membuat saya berpikir. Saya jarang menemukan alasan untuk menggunakan fitur bahasa khusus ini, dan tidak pernah memikirkan bagaimana hal itu dapat menyebabkan masalah. Sekarang, saya ingin tahu bagaimana saya bisa memanfaatkannya secara efektif with
, sambil menghindari perangkapnya.
Di mana Anda menemukan with
pernyataan itu berguna?
with
sehingga tidak ada lagi hal seperti itu.Jawaban:
Penggunaan lain terjadi pada saya hari ini, jadi saya mencari di web dengan penuh semangat dan menemukan penyebutan yang ada: Mendefinisikan Variabel di dalam Lingkup Blok .
Latar Belakang
JavaScript, meskipun memiliki kemiripan yang dangkal dengan C dan C ++, tidak membuat variabel pada blok yang didefinisikan dalam:
Mendeklarasikan penutupan dalam satu lingkaran adalah tugas umum di mana ini dapat menyebabkan kesalahan:
Karena for loop tidak memperkenalkan lingkup baru, hal yang sama
num
- dengan nilai2
- akan dibagi oleh ketiga fungsi.Lingkup baru:
let
danwith
Dengan diperkenalkannya
let
pernyataan dalam ES6 , menjadi mudah untuk memperkenalkan ruang lingkup baru bila perlu untuk menghindari masalah ini:Atau bahkan:
Hingga ES6 tersedia secara universal, penggunaan ini tetap terbatas pada browser dan pengembang terbaru yang bersedia menggunakan transpiler. Namun, kami dapat dengan mudah mensimulasikan perilaku ini menggunakan
with
:Loop sekarang berfungsi sebagaimana mestinya, membuat tiga variabel terpisah dengan nilai dari 0 hingga 2. Perhatikan bahwa variabel yang dideklarasikan di dalam blok tidak dicakup, tidak seperti perilaku blok di C ++ (dalam C, variabel harus dideklarasikan pada awal sebuah blok, jadi agak mirip). Perilaku ini sebenarnya sangat mirip dengan
let
sintaks blok yang diperkenalkan di versi browser Mozilla sebelumnya, tetapi tidak diadopsi secara luas di tempat lain.sumber
for (var i = 0; i < 3; ++i) { setTimeout ((function () { var num = i; return function () { alert (num); }; }) (), 10);}
var toString = function () { return "Hello"; }; with ({"test":1}) { console.log(toString()); };
,. Dalam lingkup pernyataan with , toString () adalah properti yang diwarisi dari Object , jadi fungsi yang didefinisikan secara eksplisit tidak dipanggil. Masih jawaban yang bagus :-)Saya telah menggunakan pernyataan with sebagai bentuk sederhana impor scoped. Katakanlah Anda memiliki semacam pembuat markup. Daripada menulis:
Anda bisa menulis:
Untuk kasus penggunaan ini, saya tidak melakukan tugas apa pun, jadi saya tidak memiliki masalah ambiguitas terkait dengan itu.
sumber
context.bezierCurveTo
seratus kali berturut-turut, Anda dapat mengatakanvar bc2 = context.bezierCurveTo;
dan kemudian pergibc2(x,x,etc);
setiap kali Anda ingin menyebutnya. Itu cukup cepat dan bahkan kurang bertele-tele, sementarawith
super lambat.Seperti yang ditunjukkan oleh komentar saya sebelumnya, saya tidak berpikir Anda dapat menggunakan
with
dengan aman tidak peduli seberapa menggoda itu dalam situasi tertentu. Karena masalahnya tidak langsung dibahas di sini, saya akan mengulanginya. Pertimbangkan kode berikutTanpa hati-hati menyelidiki panggilan fungsi itu, tidak ada cara untuk mengetahui apa yang akan program Anda setelah kode ini berjalan. Jika
user.name
sudah diatur, sekarang akan menjadiBob
. Jika tidak disetel, globalname
akan diinisialisasi atau diubahBob
danuser
objek akan tetap tanpaname
properti.Bug terjadi. Jika Anda gunakan dengan akhirnya Anda akan melakukan ini dan meningkatkan peluang program Anda akan gagal. Lebih buruk lagi, Anda mungkin menemukan kode kerja yang menetapkan global dalam blok with, baik sengaja atau melalui penulis tidak tahu tentang kekhasan konstruksi ini. Ini seperti menghadapi jatuh melalui saklar, Anda tidak tahu apakah penulis bermaksud ini dan tidak ada cara untuk mengetahui apakah "memperbaiki" kode akan memperkenalkan regresi.
Bahasa pemrograman modern penuh dengan fitur. Beberapa fitur, setelah bertahun-tahun digunakan, diketahui buruk, dan harus dihindari. Javascript
with
adalah salah satunya.sumber
Saya sebenarnya menemukan
with
pernyataan itu sangat berguna baru-baru ini. Teknik ini tidak pernah benar-benar terpikir oleh saya sampai saya memulai proyek saya saat ini - konsol baris perintah yang ditulis dalam JavaScript. Saya mencoba untuk meniru API konsol Firebug / WebKit di mana perintah khusus dapat dimasukkan ke dalam konsol tetapi mereka tidak menimpa variabel dalam lingkup global. Saya memikirkan hal ini ketika mencoba mengatasi masalah yang saya sebutkan di komentar atas jawaban Shog9 yang sangat baik .Untuk mencapai efek ini, saya menggunakan dua dengan pernyataan untuk "melapisi" lingkup di balik lingkup global:
Hal yang hebat tentang teknik ini adalah bahwa, selain dari kerugian kinerja, itu tidak menderita ketakutan biasa
with
pernyataan itu, karena kita tetap mengevaluasi dalam lingkup global - tidak ada bahaya variabel di luar ruang lingkup pseudo kita dari menjadi diubah.Saya terinspirasi untuk mengirim jawaban ini ketika, yang mengejutkan saya, saya berhasil menemukan teknik yang sama dengan yang digunakan di tempat lain - kode sumber Chromium !
EDIT: Baru memeriksa sumber Firebug, mereka menghubungkan 4 dengan pernyataan bersama untuk lebih banyak lapisan. Gila!
sumber
Ya, ya dan ya. Ada penggunaan yang sangat sah. Menonton:
Pada dasarnya setiap kait DOM atau CSS lainnya adalah penggunaan yang fantastis. Ini tidak seperti "CloneNode" yang tidak terdefinisi dan kembali ke lingkup global kecuali Anda menyimpang dari jalan dan memutuskan untuk membuatnya mungkin.
Keluhan kecepatan Crockford adalah bahwa konteks baru dibuat dengan. Konteks umumnya mahal. Saya setuju. Tetapi jika Anda baru saja membuat div dan tidak memiliki kerangka kerja untuk mengatur css Anda dan perlu menyiapkan 15 atau lebih properti CSS dengan tangan, maka membuat konteks mungkin akan lebih murah daripada pembuatan variabel dan 15 referensi:
dll ...
sumber
with
. Namun, dalam kasus khusus ini Anda hanya bisa melakukan:element.style.cssText="background: black ; color: blue ; border: 1px solid green"
extend
metode baik dari jQuery atau Underscore.js:$.extend(element.style, {fontWeight: 'bold', fontSize: '1.5em', color: '#55d', marginLeft: '2px'})
..css()
metode ini ...Anda dapat mendefinisikan fungsi pembantu kecil untuk memberikan manfaat
with
tanpa ambiguitas:sumber
with_
menjadi versi berlipat ganda berlumpur(function(_){ _.a="foo"; })(object_here);
(cara standar untuk mensimulasikan blok gaya c / java). Gunakan itu sebagai gantinya.Tampaknya tidak sepadan karena Anda dapat melakukan hal berikut:
sumber
with
.Saya tidak pernah menggunakannya, tidak melihat alasan, dan tidak merekomendasikannya.
Masalahnya
with
adalah hal itu mencegah banyak optimasi leksikal yang dapat dilakukan oleh implementasi ECMAScript. Dengan munculnya mesin cepat berbasis JIT, masalah ini mungkin akan menjadi lebih penting dalam waktu dekat.Itu mungkin terlihat seperti
with
memungkinkan untuk konstruksi yang lebih bersih (ketika, katakanlah, memperkenalkan ruang lingkup baru alih-alih pembungkus fungsi anonim yang umum atau mengganti aliasing verbose), tetapi itu benar - benar tidak sepadan . Selain penurunan kinerja, selalu ada bahaya menugaskan ke properti dari objek yang salah (ketika properti tidak ditemukan pada objek dalam ruang lingkup yang disuntikkan) dan mungkin salah memperkenalkan variabel global. IIRC, masalah terakhir adalah yang mendorong Crockford untuk merekomendasikan untuk menghindariwith
.sumber
with(){}
konstruksi seperti yang diberikan dalam jawaban lain di sini, di browser modern, saya ingin melihat mereka!with(){}
: menyiapkan ruang lingkup baru denganwith
sangat mahal pada setiap browser yang saya uji. Anda ingin menghindari ini dalam kode apa pun yang disebut sangat sering. Selain itu, Chrome menunjukkan hit dramatis untuk setiap kode yang dieksekusi dalamwith()
lingkup. Menariknya, IE memiliki karakteristik kinerja terbaik untuk kode dalamwith()
blok: memperhitungkan biaya pengaturan,with()
menyediakan cara tercepat untuk akses anggota di IE6 dan IE8 VMs (meskipun VM ini adalah keseluruhan paling lambat). Bagus, terima kasih ...with()
hampir merupakan urutan besarnya lebih lambat di Chrome, dan dua kali lebih cepat di IE ...!Visual Basic.NET memiliki
With
pernyataan serupa . Salah satu cara yang lebih umum saya menggunakannya adalah dengan cepat mengatur sejumlah properti. Dari pada:, Saya bisa menulis:
Ini bukan hanya masalah kemalasan. Itu juga membuat kode lebih mudah dibaca. Dan tidak seperti JavaScript, itu tidak menderita ambiguitas, karena Anda harus mengawali semua yang dipengaruhi oleh pernyataan dengan
.
(titik). Jadi, dua yang berikut ini jelas berbeda:vs.
Yang pertama adalah
someObject.Foo
; yang terakhir adalahFoo
di luar ruang lingkupsomeObject
.Saya menemukan bahwa kurangnya perbedaan JavaScript membuatnya jauh kurang berguna daripada varian Visual Basic, karena risiko ambiguitas terlalu tinggi. Selain itu,
with
masih merupakan ide kuat yang dapat membuat keterbacaan lebih baik.sumber
Anda bisa menggunakan
with
untuk memperkenalkan konten objek sebagai variabel lokal ke blok, seperti yang dilakukan dengan mesin template kecil ini .sumber
Menggunakan "with" dapat membuat kode Anda lebih kering.
Pertimbangkan kode berikut:
Anda dapat mengeringkannya sebagai berikut:
Saya kira itu tergantung apakah Anda memiliki preferensi untuk keterbacaan atau ekspresif.
Contoh pertama lebih mudah dibaca dan mungkin direkomendasikan untuk sebagian besar kode. Namun sebagian besar kode cukup jinak. Yang kedua sedikit lebih tidak jelas tetapi menggunakan sifat ekspresif dari bahasa untuk mengurangi ukuran kode dan variabel berlebihan.
Saya membayangkan orang-orang yang suka Java atau C # akan memilih cara pertama (object.member) dan mereka yang lebih suka Ruby atau Python akan memilih yang terakhir.
sumber
Saya pikir penggunaan yang jelas adalah sebagai jalan pintas. Jika Anda mis. Menginisialisasi objek, Anda cukup menyimpan banyak mengetik "ObjectName." Jenis seperti slot "dengan-slot" yang memungkinkan Anda menulis
yang sama dengan menulis
Lebih jelas mengapa ini merupakan jalan pintas daripada saat bahasa Anda mengizinkan "Objectname.foo" tapi tetap saja.
sumber
with-slots
mengharuskan Anda untuk menentukan slot mana yang Anda gunakan, sedangkanwith
akan menggunakan slot apa pun yang terikat saat runtime.Memiliki pengalaman dengan Delphi, saya akan mengatakan bahwa menggunakan dengan harus menjadi optimasi ukuran terakhir, mungkin dilakukan oleh beberapa jenis algoritma minimizer javascript dengan akses ke analisis kode statis untuk memverifikasi keamanannya.
Masalah pelingkupan yang bisa Anda lakukan dengan penggunaan bebas pernyataan with bisa menjadi masalah besar di a ** dan saya tidak ingin siapa pun mengalami sesi debug untuk mengetahui apa yang terjadi .. dalam kode Anda , hanya untuk mengetahui bahwa ia menangkap anggota objek atau variabel lokal yang salah, alih-alih variabel lingkup global atau luar yang Anda maksud.
VB dengan statemen lebih baik, karena membutuhkan titik-titik untuk mendisplambasikan pelingkupan, tetapi Delphi dengan statemen adalah pistol bermuatan dengan hairtrigger, dan menurut saya seolah-olah javascript yang cukup mirip untuk menjamin peringatan yang sama.
sumber
Menggunakan dengan tidak dianjurkan, dan dilarang dalam mode ketat ECMAScript 5. Alternatif yang disarankan adalah menetapkan objek yang propertinya ingin Anda akses ke variabel sementara.
Sumber: Mozilla.org
sumber
Pernyataan with dapat digunakan untuk mengurangi ukuran kode atau untuk anggota kelas pribadi, contoh:
Dengan-pernyataan sangat berguna jika Anda ingin memodifikasi ruang lingkup, apa yang diperlukan untuk memiliki ruang lingkup global Anda sendiri yang dapat Anda manipulasi saat runtime. Anda dapat meletakkan konstanta di atasnya atau fungsi pembantu tertentu yang sering digunakan seperti misalnya "toUpper", "toLower" atau "isNumber", "clipNumber" aso ..
Tentang kinerja buruk yang sering saya baca: Melingkupi fungsi tidak akan berdampak pada kinerja, pada kenyataannya dalam FF saya, fungsi yang dilingkupi berjalan lebih cepat daripada yang tidak dicentang:
Jadi dengan cara yang disebutkan di atas digunakan dengan-pernyataan tidak memiliki efek negatif pada kinerja, tetapi bagus karena mengurangi ukuran kode, apa dampak penggunaan memori pada perangkat mobile.
sumber
Menggunakan dengan juga membuat kode Anda lebih lambat dalam banyak implementasi, karena semuanya sekarang terbungkus dalam ruang lingkup tambahan untuk pencarian. Tidak ada alasan yang sah untuk digunakan dengan JavaScript.
sumber
var obj={a:0,b:0,c:0};var d=+new Date;with(obj){for(var i=0;i<1000000;++i){a+=1;b+=1;c+=1}}+new Date-d;
memberi rata-rata 2500, sementaravar obj={a:0,b:0,c:0};var d=+new Date;for(var i=0;i<1000000;++i){obj.a+=1;obj.b+=1;obj.c+=1}+new Date-d;
memberi rata-rata 750, membuat yang menggunakan lebih dari 3 kali lebih lambat.with
kode dan 903 tanpa. Dengan perbedaan kecil ini bahkan dalam satu lingkaran ketat saya akan membuat pilihan berdasarkan kesederhanaan pengkodean dan kemudahan refactoring berdasarkan kasus per kasus sebelum mengkhawatirkan kinerja.Saya pikir dengan-pernyataan bisa berguna ketika mengubah bahasa template menjadi JavaScript. Misalnya JST di base2 , tapi saya sudah sering melihatnya.
Saya setuju orang bisa memprogram ini tanpa dengan pernyataan. Tetapi karena tidak memberikan masalah, itu adalah penggunaan yang sah.
sumber
Ini bagus untuk menempatkan kode yang berjalan di lingkungan yang relatif rumit ke dalam wadah: Saya menggunakannya untuk membuat ikatan lokal untuk "jendela" dan untuk menjalankan kode yang dimaksudkan untuk browser web.
sumber
Saya pikir objek yang digunakan secara literal menarik, seperti pengganti drop-in untuk menggunakan penutupan
atau dengan pernyataan setara dengan penutupan
Saya pikir risiko sebenarnya adalah secara kebetulan minipulasi variabel yang bukan bagian dari pernyataan with, oleh karena itu saya suka objek literal diteruskan, Anda dapat melihat dengan tepat apa yang akan ada dalam konteks yang ditambahkan dalam kode.
sumber
Saya membuat fungsi "menggabungkan" yang menghilangkan beberapa ambiguitas ini dengan
with
pernyataan:Saya dapat menggunakannya dengan cara yang sama
with
, tetapi saya tahu itu tidak akan memengaruhi ruang lingkup apa pun yang tidak saya inginkan.Pemakaian:
sumber
Untuk beberapa potongan kode pendek, saya ingin menggunakan fungsi trigonometri seperti
sin
,cos
dll dalam mode derajat alih-alih dalam mode radiasi. Untuk tujuan ini, saya menggunakanAngularDegree
objek:Lalu saya bisa menggunakan fungsi trigonometri dalam mode derajat tanpa gangguan bahasa lebih lanjut di
with
blok:Ini berarti: Saya menggunakan objek sebagai kumpulan fungsi, yang saya aktifkan di wilayah kode terbatas untuk akses langsung. Saya menemukan ini berguna.
sumber
with
pernyataan dengan cara ini, itu hanya membuat kode sulit dibaca karena Anda tidak tahu fungsi mana yang global dan fungsi mana yang disebut dalam lingkup dengan objek, jadi jika ada fungsi dengan cara apa pun tidak didefinisikan dalam objek lingkup kemudian akan mencoba mengaksesnya di namespace globalz = Math.atan2( Math.sin(d * Math.PI / 180), Math.cos( pol.lat * Math.PI / 180) * Math.tan( pos.lat * Math.PI / 180 ) - Math.sin( pol.lat * Math.PI / 180 ) * Math.cos( d * Math.PI / 180) ) * 180 / Math.PI;
akan memberikan hasil yang sama, tetapi ini adalah horor.with
yang akan membuat Anda bingung.Saya pikir kegunaannya
with
dapat bergantung pada seberapa baik kode Anda ditulis. Misalnya, jika Anda menulis kode yang muncul seperti ini:maka Anda bisa membantah bahwa
with
akan meningkatkan keterbacaan kode dengan melakukan ini:Sebaliknya, bisa dikatakan bahwa Anda melanggar Hukum Demeter , tetapi, sekali lagi, mungkin tidak. Saya ngelantur =).
Di atas segalanya, ketahuilah bahwa Douglas Crockford merekomendasikan untuk tidak menggunakan
with
. Saya mendesak Anda untuk memeriksa posting blognya mengenaiwith
dan alternatifnya di sini .sumber
Saya hanya benar-benar tidak melihat bagaimana menggunakan dengan lebih mudah dibaca daripada hanya mengetik objek. Saya tidak berpikir itu kurang terbaca, tetapi saya tidak berpikir itu lebih mudah dibaca juga.
Seperti kata lassevk, saya pasti bisa melihat bagaimana menggunakan dengan akan lebih rentan kesalahan daripada hanya menggunakan sintaks "object.member" yang sangat eksplisit.
sumber
Anda harus melihat validasi formulir dalam javascript di W3schools http://www.w3schools.com/js/js_form_validation.asp mana bentuk objek "dipindai" untuk menemukan input dengan nama 'email'
Tetapi saya telah memodifikasinya untuk mendapatkan dari formulir APA SAJA semua bidang memvalidasi tidak kosong, terlepas dari nama atau jumlah bidang dalam formulir. Yah saya sudah menguji hanya bidang teks.
Tetapi dengan () membuat segalanya lebih sederhana. Berikut kodenya:
sumber
CoffeeScript ini Coco garpu memiliki
with
kata kunci, tapi itu hanya setthis
(juga ditulis sebagai@
di CoffeeScript / Coco) ke objek target dalam blok. Ini menghilangkan ambiguitas dan mencapai kepatuhan mode ketat ES5:sumber
Berikut ini adalah penggunaan yang baik untuk
with
: menambahkan elemen baru ke Obyek Literal, berdasarkan nilai yang disimpan dalam Objek itu. Berikut ini contoh yang baru saya gunakan hari ini:Saya memiliki satu set ubin yang mungkin (dengan bukaan menghadap atas, bawah, kiri, atau kanan) yang dapat digunakan, dan saya ingin cara cepat untuk menambahkan daftar ubin yang akan selalu ditempatkan dan dikunci pada awal permainan . Saya tidak ingin terus mengetik
types.tbr
untuk setiap jenis dalam daftar, jadi saya hanya menggunakannyawith
.sumber
Anda dapat menggunakan dengan untuk menghindari keharusan mengelola arity secara eksplisit saat menggunakan require.js:
Implementasi requirejs.declare:
sumber
Seperti yang ditunjukkan oleh Andy E dalam komentar jawaban Shog9, perilaku yang berpotensi tidak terduga ini terjadi saat menggunakan
with
dengan objek literal:Bukan berarti perilaku tak terduga tidak sudah menjadi ciri khas
with
.Jika Anda benar-benar masih ingin menggunakan teknik ini, setidaknya gunakan objek dengan prototipe nol.
Tetapi ini hanya akan bekerja di ES5 +. Juga jangan gunakan
with
.sumber
Saya sedang mengerjakan proyek yang akan memungkinkan pengguna untuk mengunggah kode untuk mengubah perilaku bagian dari aplikasi. Dalam skenario ini, saya telah menggunakan
with
klausa untuk menjaga kode mereka dari memodifikasi apa pun di luar ruang lingkup yang saya ingin mereka mainkan. Bagian (disederhanakan) dari kode yang saya gunakan untuk melakukan ini adalah:Kode ini memastikan (agak) bahwa kode yang ditentukan pengguna tidak memiliki akses ke objek yang dicakup secara global seperti
window
maupun ke variabel lokal saya melalui penutupan.Seperti kata bijak, saya masih harus melakukan pemeriksaan kode statis pada kode yang dikirimkan pengguna untuk memastikan mereka tidak menggunakan cara licik lainnya untuk mengakses lingkup global. Misalnya, kode yang ditentukan pengguna berikut mengambil akses langsung ke
window
:sumber
Saya
intinya
Bisakah Anda mempercayai kode berkualitas rendah? Tidak, kami melihat bahwa itu dibuat benar-benar tidak dapat dibaca. Contoh ini tidak dapat disangkal membuktikan bahwa tidak perlu dengan pernyataan, jika saya mengambil hak keterbacaan;)
sumber