Pertanyaan wawancara Javascript: make [1,2,3] .sum () run
Javascript wawancara pertanyaan: membuat [1,2,3].sum()kode yang tepat dijalankan tanpa menggunakan Prototypedan Object.defineProperty, Object.defineProperties.
Karena ini adalah pertanyaan wawancara, saya berasumsi ada cara untuk membuatnya berhasil?
Setiap bantuan / petunjuk arah dihargai.
Terima kasih
Jawaban
Pendahuluan: Pertanyaan seperti ini tidak benar-benar menunjukkan bahwa seseorang adalah pemrogram yang "baik", itu hanya berarti mereka terbiasa dengan trik dalam bahasa yang tidak mengarah ke kode yang lebih dapat dipelihara . Saya akan berhati-hati bekerja untuk perusahaan atau tim yang secara teratur menggunakan trik seperti ini.
(Dan dalam kasus pribadi saya: Saya bekerja pada mesin JavaScript Chakra ketika saya menjadi seorang SE di Microsoft dan saya suka berpikir bahwa saya tahu JavaScript / ECMAScript dengan sangat baik dan saya masih harus berpikir lama tentang bagaimana ini bisa dilakukan tanpa menggunakan prototypeatau defineProperty- jadi itu sebabnya menurut saya ini bukan pertanyaan wawancara teknis yang baik jika mereka mengharapkan jawaban langsung - tetapi jika ini adalah pertanyaan wawancara yang dimaksudkan untuk mendorong Anda mengajukan pertanyaan kepada pewawancara maka itu berbeda).
Opsi 1: Penangan kesalahan global:
Inilah cara yang mengerikan :
window.addEventListener( 'error', function( e ) {
if( e.error instanceof ErrorEvent || e.error instanceof TypeError ) {
const msg = e.error.message;
const suffixIdx = msg.indexOf( ".sum is not a function" );
if( suffixIdx > -1 ) {
const arrayStr = msg.substring( 0, suffixIdx );
const arr = eval( arrayStr ); // <-- lolno
const total = arr.reduce( ( sum, e ) => sum + e, 0 );
console.log( total ); // 6
}
}
} );
[1,2,3].sum()
@NenadVracar telah memposting versi sederhana yang menghindari eval, meskipun menggunakan lokal try:
try {
[1,2,3].sum()
} catch (err) {
const result = err.message
.match(/\[(.*?)\]/)[1]
.split(',')
.reduce((r, e) => r + +e, 0)
console.log(result)
}
Opsi 2: Ganti Arraykonstruktor
Jika Anda menggunakan mesin JavaScript yang lebih lama (dibuat sebelum 2010 atau ECMAScript 5), maka skrip yang menimpa Arraykonstruktor akan menggunakan konstruktor tersebut saat skrip menemukan literal array, dan .summetode tersebut dapat ditambahkan seperti itu:
Array = function() { // <-- THIS WILL NOT WORK IN BROWSERS MADE AFTER 2010!
this.sum = function() {
var total = 0;
for( var i = 0; i < this.length; i++ ) {
total += this[i];
}
return total;
};
};
let total = [1,2,3].sum();
console.log( total );
Opsi 3: Bersikap licik dengan prototypeproperti:
Seperti yang disebutkan orang lain di komentar, Anda masih dapat mengubah prototypeanggota atau menggunakan Object.definePropertyjika Anda mengakses anggota tersebut sebagai string:
Array[ 'proto' + 'type' ].sum = function() {
var total = 0;
for( var i = 0; i < this.length; i++ ) {
total += this[i];
}
return total;
};
let total = [1,2,3].sum();
console.log( total );
Seberapa banyak kita bisa mengatasi garis di sini?
Dengan asumsi bahwa kita ingin baris berikut berfungsi [1, 2, 3].sum();maka kita dapat dengan mudah membuatnya melakukan sesuatu . Perhatikan bahwa karena aturan penyisipan titik koma otomatis , apa yang Anda miliki tidak diperlukan untuk menjadi sebuah array. Mungkin akses array dengan operator koma di dalamnya.
({3: {sum: () => console.log(6)}}) //<-- object
[1,2,3].sum(); //<-- array access
Atau untuk lebih jelasnya, berikut ini padanan kode:
const obj = {
3: {
sum: () => console.log(6)
}
};
obj[3].sum(); //<-- array access
Karena, saya tidak melihat definisi tentang apa yang sumharus dilakukan, di atas mencakup semua persyaratan yang tercantum - tidak ada protoype shenanigans, tidak ada properti tambahan.
Oke, secara teknis, sumtidak menjumlahkan apa pun, tetapi berikut adalah solusinya: definisikan seperti ini
sum: (a, b) => a + b
Sekarang, secara teknis ini adalah fungsi yang menjumlahkan dua angka. Tidak ada persyaratan untuk menjumlahkan urutan 1, 2, 3yang muncul sebelum memanggil sum, setelah semua.
Ini satu cara:
[1,2,3].__proto__.sum = () => { console.log('this runs!'); }
[1,2,3].sum();
Secara teknis Anda tidak menggunakan Prototype, Anda sedang menggunakan __proto__. Yang sama dengan nama yang berbeda ... (tetapi hanya untuk contoh)