Saya diberitahu hari ini bahwa mungkin untuk menjalankan fungsi tanpa tanda kurung. Satu - satunya cara yang saya bisa pikirkan adalah menggunakan fungsi like apply
atau call
.
f.apply(this);
f.call(this);
Tapi ini membutuhkan tanda kurung apply
dan call
meninggalkan kita di titik awal. Saya juga mempertimbangkan ide untuk meneruskan fungsi ke semacam pengendali acara seperti setTimeout
:
setTimeout(f, 500);
Tetapi kemudian pertanyaannya menjadi "bagaimana Anda memohon setTimeout
tanpa tanda kurung?"
Jadi apa solusi untuk teka-teki ini? Bagaimana Anda bisa menjalankan fungsi dalam Javascript tanpa menggunakan tanda kurung?
javascript
Mike Cluck
sumber
sumber
<insert any solution>
secara objektif lebih baik atau lebih bermanfaat daripadaf()
.Jawaban:
Ada beberapa cara berbeda untuk memanggil suatu fungsi tanpa tanda kurung.
Mari kita asumsikan Anda memiliki fungsi ini didefinisikan:
Kemudian di sini ikuti beberapa cara untuk menelepon
greet
tanpa tanda kurung:1. Sebagai Pembuat
Dengan
new
Anda dapat memanggil fungsi tanpa tanda kurung:Dari MDN pada
new
oprator :2. Sebagai
toString
atauvalueOf
ImplementasitoString
danvalueOf
merupakan metode khusus: mereka dipanggil secara implisit ketika konversi diperlukan:Anda dapat (ab) menggunakan pola ini untuk memanggil
greet
tanpa tanda kurung:Atau dengan
valueOf
:valueOf
dantoString
yang sebenarnya disebut dari @@ toPrimitive metode (sejak ES6), dan sehingga Anda juga dapat menerapkan bahwa metode:2.b Mengesampingkan
valueOf
Prototipe FungsiAnda dapat mengambil ide sebelumnya untuk mengganti
valueOf
metode padaFunction
prototipe :Setelah Anda selesai melakukannya, Anda dapat menulis:
Dan meskipun ada tanda kurung di telepon, doa pemicu yang sebenarnya tidak memiliki tanda kurung. Lihat lebih lanjut tentang ini di blog "Metode pemanggilan dalam JavaScript, tanpa benar-benar memanggilnya"
3. Sebagai Generator
Anda bisa mendefinisikan fungsi generator (dengan
*
), yang mengembalikan iterator . Anda dapat memanggilnya menggunakan sintaks spread atau denganfor...of
sintaks.Pertama kita membutuhkan varian generator dari
greet
fungsi aslinya :Dan kemudian kita menyebutnya tanpa tanda kurung dengan mendefinisikan metode @@ iterator :
Biasanya generator memiliki
yield
kata kunci di suatu tempat, tetapi fungsi tersebut tidak diperlukan untuk dipanggil.Pernyataan terakhir memanggil fungsi, tetapi itu juga bisa dilakukan dengan merusak :
atau
for ... of
konstruk, tetapi memiliki tanda kurung sendiri:Perhatikan bahwa Anda dapat melakukan hal di atas dengan
greet
fungsi asli juga, tetapi itu akan memicu pengecualian dalam proses, setelahgreet
dieksekusi (diuji pada FF dan Chrome). Anda dapat mengelola pengecualian dengantry...catch
blok.4. Sebagai Getter
@ jehna1 punya jawaban penuh untuk ini, jadi beri dia pujian. Berikut adalah cara untuk memanggil fungsi kurung-kurang pada lingkup global, menghindari metode yang sudah usang
__defineGetter__
. Ini menggunakanObject.defineProperty
sebagai gantinya.Kita perlu membuat varian
greet
fungsi asli untuk ini:Lalu:
Ganti
window
dengan apa pun objek global Anda.Anda bisa memanggil
greet
fungsi asli tanpa meninggalkan jejak pada objek global seperti ini:Tetapi orang dapat berargumen bahwa kami memiliki tanda kurung di sini (meskipun mereka tidak terlibat dalam doa yang sebenarnya).
5. Sebagai Fungsi Tag
Karena ES6 Anda dapat memanggil fungsi yang melewatinya sebagai templat literal dengan sintaks ini:
Lihat "Literal Templat Tagged" .
6. Sebagai Proxy Handler
Sejak ES6, Anda dapat menetapkan proxy :
Dan kemudian membaca nilai properti apa pun akan meminta
greet
:Ada banyak variasi dari ini. Satu lagi contoh:
7. Sebagai pemeriksa contoh
The
instanceof
Operator mengeksekusi@@hasInstance
metode pada operan kedua, ketika didefinisikan:sumber
valueOf
.func``;
'1' |> alert
Cara termudah untuk melakukannya adalah dengan
new
operator:Walaupun itu tidak lazim dan tidak wajar, ia bekerja dan sangat legal.
The
new
Operator tidak memerlukan tanda kurung jika tidak ada parameter yang digunakan.sumber
!f
menghasilkan hal yang sama, tanpa membuat instance fungsi konstruktor (yang membutuhkan pembuatan konteks baru ini). Ini jauh lebih berkinerja dan digunakan di banyak perpustakaan populer (seperti Bootstrap).+
,-
,~
) di perpustakaan tersebut, adalah untuk menyimpan byte dalam versi diminimalkan perpustakaan di mana nilai kembali tidak diperlukan. (Yaitu!function(){}()
) Sintaks pemanggilan diri yang biasa adalah(function(){})()
(sayangnya sintaksnyafunction(){}()
bukan cross-browser) Karena fungsi pemanggilan diri paling atas biasanya tidak memiliki apa-apa untuk dikembalikan, biasanya target dari teknik penyimpanan byte inifunction foo() { alert("Foo!") };
Sebagai contoh:!foo
pengembalianfalse
Anda dapat menggunakan getter dan setter.
Jalankan skrip ini hanya dengan:
Edit:
Kita bahkan dapat berdebat!
Edit 2:
Anda juga dapat mendefinisikan fungsi global yang dapat dijalankan tanpa tanda kurung:
Dan dengan argumen:
Penolakan:
Seperti @MonkeyZeus menyatakan: Jangan pernah Anda menggunakan kode ini dalam produksi, tidak peduli seberapa bagus niat Anda.
sumber
__defineGetter__
sudah usang. GunakanObject.defineProperty
sebagai gantinya.Berikut ini contoh untuk situasi tertentu:
Meskipun pernyataan itu tidak benar-benar memohon tetapi akan menyebabkan doa di masa depan .
Tapi, saya pikir area abu-abu mungkin ok untuk teka-teki seperti ini :)
sumber
Jika kami menerima pendekatan berpikir lateral, di browser ada beberapa API yang dapat kami penyalahgunaan untuk mengeksekusi JavaScript sewenang-wenang, termasuk memanggil fungsi, tanpa karakter tanda kurung yang sebenarnya.
1.
location
danjavascript:
protokol:Salah satu teknik tersebut adalah dengan menyalahgunakan
javascript:
protokol padalocation
tugas.Contoh kerja:
Meskipun secara teknis
\x28
dan\x29
masih tanda kurung setelah kode dievaluasi, aktual(
dan)
karakter tidak muncul. Tanda kurung dilepaskan dalam serangkaian JavaScript yang akan dievaluasi saat penugasan.2.
onerror
daneval
:Demikian pula, tergantung pada peramban kita dapat menyalahgunakan global
onerror
, dengan menyetelnya keeval
, dan melemparkan sesuatu yang akan dikencangkan menjadi JavaScript yang valid. Yang ini lebih rumit, karena peramban tidak konsisten dalam perilaku ini, tetapi inilah contoh untuk Chrome.Contoh kerja untuk Chrome (bukan Firefox, yang lain belum diuji):
Ini berfungsi di Chrome karena
throw'test'
akan diteruskan'Uncaught test'
sebagai argumen pertamaonerror
, yang merupakan JavaScript yang hampir valid. Jika kita melakukannya,throw';test'
itu akan berlalu'Uncaught ;test'
. Sekarang kami memiliki JavaScript yang valid! Cukup tentukanUncaught
, dan ganti tes dengan payload.Kesimpulannya:
Kode seperti itu benar-benar mengerikan , dan tidak boleh digunakan , tetapi kadang-kadang digunakan dalam serangan XSS, sehingga moral cerita tidak bergantung pada penyaringan tanda kurung untuk mencegah XSS. Menggunakan CSP untuk mencegah kode seperti itu juga merupakan ide bagus.
sumber
eval
dan menulis string tanpa benar-benar menggunakan karakter tanda kurung.eval
biasanya membutuhkan tanda kurung, karena itu filter ini menghindari hack.\x28
dan\x29
masih kurung.'\x28' === '('
.Di ES6, Anda memiliki apa yang disebut Tagged Template Literals .
Sebagai contoh:
sumber