Saya tahu ini digunakan untuk membuat argumen array nyata, tapi saya tidak mengerti apa yang terjadi ketika menggunakan Array.prototype.slice.call(arguments)
Saya tahu ini digunakan untuk membuat argumen array nyata, tapi saya tidak mengerti apa yang terjadi ketika menggunakan Array.prototype.slice.call(arguments)
Jawaban:
Apa yang terjadi di bawah tenda adalah bahwa ketika .slice()
dipanggil secara normal, this
adalah Array, dan kemudian hanya beralih ke Array itu, dan melakukan tugasnya.
Bagaimana this
di .slice()
fungsi Array? Karena ketika Anda melakukannya:
object.method();
... object
secara otomatis menjadi nilai this
dalam method()
. Demikian dengan:
[1,2,3].slice()
... [1,2,3]
Array ditetapkan sebagai nilai this
in .slice()
.
Tetapi bagaimana jika Anda bisa mengganti sesuatu yang lain sebagai this
nilainya? Selama apapun yang Anda gantikan memiliki .length
properti numerik , dan banyak properti yang merupakan indeks numerik, itu harus berfungsi. Jenis objek ini sering disebut objek seperti array .
Metode .call()
dan .apply()
membiarkan Anda secara manual mengatur nilai this
dalam suatu fungsi. Jadi jika kita menyetel nilai this
in .slice()
ke objek mirip array , anggap.slice()
saja itu berfungsi dengan Array, dan akan melakukan hal tersebut.
Ambil objek sederhana ini sebagai contoh.
var my_object = {
'0': 'zero',
'1': 'one',
'2': 'two',
'3': 'three',
'4': 'four',
length: 5
};
Ini jelas bukan Array, tetapi jika Anda dapat mengaturnya sebagai this
nilai .slice()
, maka itu hanya akan berfungsi, karena terlihat cukup seperti Array untuk .slice()
dapat bekerja dengan baik.
var sliced = Array.prototype.slice.call( my_object, 3 );
Contoh: http://jsfiddle.net/wSvkv/
Seperti yang dapat Anda lihat di konsol, hasilnya adalah apa yang kami harapkan:
['three','four'];
Jadi inilah yang terjadi ketika Anda menetapkan arguments
objek sebagai this
nilai .slice()
. Karena arguments
memiliki .length
properti dan banyak indeks numerik, .slice()
cukup berfungsi seperti bekerja pada Array nyata.
Array.prototype.slice
deskripsi metode.
for-in
Pernyataan yang tidak menjamin pesanan. Algoritma yang digunakan oleh .slice()
mendefinisikan urutan numerik dimulai dengan 0
dan diakhiri (non-inklusif) dengan .length
objek yang diberikan (atau Array atau apa pun). Jadi pesanan dijamin konsisten di semua implementasi.
var obj = {2:"two", 0:"zero", 1: "one"}
. Jika kita gunakan for-in
untuk menyebutkan objek, tidak ada jaminan pesanan. Tetapi jika kita menggunakan for
, kita secara manual dapat menegakkan perintah: for (var i = 0; i < 3; i++) { console.log(obj[i]); }
. Sekarang kita tahu bahwa properti objek akan tercapai dalam urutan numerik naik yang kita tetapkan oleh for
loop kita . Itu yang .slice()
dilakukannya. Tidak peduli jika ia memiliki Array yang sebenarnya. Itu baru saja dimulai 0
dan mengakses properti dalam loop menanjak.
The arguments
objek adalah tidak benar-benar sebuah contoh dari Array, dan tidak memiliki metode Array. Jadi, arguments.slice(...)
tidak akan berfungsi karena objek argumen tidak memiliki metode slice.
Array memiliki metode ini, dan karena arguments
objeknya sangat mirip dengan array, keduanya kompatibel. Ini berarti bahwa kita dapat menggunakan metode array dengan objek argumen. Dan karena metode array dibangun dengan mempertimbangkan array, mereka akan mengembalikan array daripada objek argumen lainnya.
Jadi mengapa digunakan Array.prototype
? The Array
adalah objek yang kita buat array baru dari ( new Array()
), dan ini array baru lulus metode dan properti, seperti slice. Metode-metode ini disimpan dalam [Class].prototype
objek. Jadi, demi efisiensi, alih-alih mengakses metode slice dengan (new Array()).slice.call()
atau [].slice.call()
, kami hanya mendapatkannya langsung dari prototipe. Ini agar kita tidak perlu menginisialisasi array baru.
Tetapi mengapa kita harus melakukan ini sejak awal? Nah, seperti yang Anda katakan, itu mengubah objek argumen menjadi contoh Array. Namun, alasan mengapa kita menggunakan slice lebih merupakan "retasan" daripada apa pun. Metode slice akan mengambil irisan array dan mengembalikan irisan itu sebagai array baru. Melewati tidak ada argumen untuk itu (selain objek argumen sebagai konteksnya) menyebabkan metode slice untuk mengambil potongan lengkap dari "array" yang diteruskan (dalam hal ini, objek argumen) dan mengembalikannya sebagai array baru.
Biasanya, menelepon
var b = a.slice();
akan menyalin array a
ke b
. Namun, kami tidak bisa melakukannya
var a = arguments.slice();
karena arguments
bukan array nyata, dan tidak memiliki slice
sebagai metode. Array.prototype.slice
adalah slice
fungsi untuk array, dan call
menjalankan fungsi dengan this
set ke arguments
.
prototype
? bukan metode slice
asli Array
?
Array
adalah fungsi konstruktor, dan "kelas" yang sesuai adalah Array.prototype
. Anda juga dapat menggunakan[].slice
slice
adalah metode dari setiap Array
instance, tetapi bukan Array
fungsi konstruktor. Anda gunakan prototype
untuk mengakses metode dari contoh teoritis konstruktor.
Pertama, Anda harus membaca cara fungsi doa berfungsi dalam JavaScript . Saya kira itu saja sudah cukup untuk menjawab pertanyaan Anda. Tetapi inilah ringkasan dari apa yang terjadi:
Array.prototype.slice
ekstrak metode dari 's prototipe . Tetapi memanggilnya secara langsung tidak akan berhasil, karena ini adalah metode (bukan fungsi) dan karena itu memerlukan konteks (objek panggilan, ), jika tidak maka akan dibuang .slice
Array
this
Uncaught TypeError: Array.prototype.slice called on null or undefined
The call()
Metode memungkinkan Anda untuk menentukan konteks metode ini, pada dasarnya membuat dua panggilan ini setara:
someObject.slice(1, 2);
slice.call(someObject, 1, 2);
Kecuali yang pertama membutuhkan slice
metode untuk ada dalam someObject
rantai prototipe (seperti halnya untuk Array
), sedangkan yang terakhir memungkinkan konteks ( someObject
) untuk secara manual diteruskan ke metode.
Juga, yang terakhir adalah kependekan dari:
var slice = Array.prototype.slice;
slice.call(someObject, 1, 2);
Yang sama dengan:
Array.prototype.slice.call(someObject, 1, 2);
// We can apply `slice` from `Array.prototype`:
Array.prototype.slice.call([]); //-> []
// Since `slice` is available on an array's prototype chain,
'slice' in []; //-> true
[].slice === Array.prototype.slice; //-> true
// … we can just invoke it directly:
[].slice(); //-> []
// `arguments` has no `slice` method
'slice' in arguments; //-> false
// … but we can apply it the same way:
Array.prototype.slice.call(arguments); //-> […]
// In fact, though `slice` belongs to `Array.prototype`,
// it can operate on any array-like object:
Array.prototype.slice.call({0: 1, length: 1}); //-> [1]
Array.prototype.slice.call (argumen) adalah cara kuno untuk mengubah argumen menjadi array.
Di ECMAScript 2015, Anda dapat menggunakan Array.from atau operator spread:
let args = Array.from(arguments);
let args = [...arguments];
Itu karena, seperti catatan MDN
Objek argumen bukan array. Ini mirip dengan array, tetapi tidak memiliki properti array apa pun kecuali panjang. Misalnya, tidak memiliki metode pop. Namun itu dapat dikonversi menjadi array nyata:
Di sini kita memanggil slice
objek asli Array
dan bukan pada implementasinya dan itu sebabnya tambahan.prototype
var args = Array.prototype.slice.call(arguments);
Jangan lupa, bahwa dasar-dasar tingkat rendah dari perilaku ini adalah tipe-casting yang terintegrasi dalam mesin-JS sepenuhnya.
Slice hanya mengambil objek (berkat properti arguments.length yang ada) dan mengembalikan array-objek yang dilemparkan setelah melakukan semua operasi.
Logika yang sama dengan yang Anda dapat uji jika Anda mencoba memperlakukan metode-String dengan nilai INT:
String.prototype.bold.call(11); // returns "<b>11</b>"
Dan itu menjelaskan pernyataan di atas.
Ia menggunakan slice
metode array memiliki dan menyebutnya dengan yang this
menjadi arguments
objek. Ini berarti ia memanggilnya seolah-olah Anda arguments.slice()
berasumsi arguments
memiliki metode seperti itu.
Membuat slice tanpa argumen apa pun hanya akan mengambil semua elemen - jadi itu hanya menyalin elemen dari arguments
ke array.
Anggap Anda memiliki: function.apply(thisArg, argArray )
Metode terapkan memanggil fungsi, meneruskan objek yang akan terikat dengan ini dan array argumen opsional.
Metode slice () memilih bagian dari array, dan mengembalikan array baru.
Jadi ketika Anda memanggil Array.prototype.slice.apply(arguments, [0])
metode slice array dipanggil (ikat) pada argumen.
Mungkin agak terlambat, tetapi jawaban untuk semua kekacauan ini adalah bahwa panggilan () digunakan dalam JS untuk warisan. Jika kita membandingkan ini dengan Python atau PHP, misalnya, panggilan digunakan masing-masing sebagai super (). init () atau parent :: _ construct ().
Ini adalah contoh penggunaannya yang menjelaskan semua:
function Teacher(first, last, age, gender, interests, subject) {
Person.call(this, first, last, age, gender, interests);
this.subject = subject;
}
Referensi: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance
ketika .slice () dipanggil secara normal, ini adalah Array, dan kemudian hanya mengulangi Array itu, dan melakukan tugasnya.
//ARGUMENTS
function func(){
console.log(arguments);//[1, 2, 3, 4]
//var arrArguments = arguments.slice();//Uncaught TypeError: undefined is not a function
var arrArguments = [].slice.call(arguments);//cp array with explicity THIS
arrArguments.push('new');
console.log(arrArguments)
}
func(1,2,3,4)//[1, 2, 3, 4, "new"]
Saya hanya menulis ini untuk mengingatkan diri saya sendiri ...
Array.prototype.slice.call(arguments);
== Array.prototype.slice(arguments[1], arguments[2], arguments[3], ...)
== [ arguments[1], arguments[2], arguments[3], ... ]
Atau cukup gunakan fungsi praktis ini $ A untuk mengubah sebagian besar hal menjadi sebuah array.
function hasArrayNature(a) {
return !!a && (typeof a == "object" || typeof a == "function") && "length" in a && !("setInterval" in a) && (Object.prototype.toString.call(a) === "[object Array]" || "callee" in a || "item" in a);
}
function $A(b) {
if (!hasArrayNature(b)) return [ b ];
if (b.item) {
var a = b.length, c = new Array(a);
while (a--) c[a] = b[a];
return c;
}
return Array.prototype.slice.call(b);
}
contoh penggunaan ...
function test() {
$A( arguments ).forEach( function(arg) {
console.log("Argument: " + arg);
});
}