Function.prototype.call2 = function(context) { context.fn = this; var args = []; for(var i = 1, len = arguments.length; i < len; i++) { args.push('arguments[' + i + ']'); } eval('context.fn(' + args +')'); delete context.fn; }
Ia adalah untuk mensimulasikan pelaksanaan panggilan Mengapa anda perlu menolak rentetan dan kemudian menggunakan eval seterusnya? Mengapa tidak lulus terus dalam argumen[i] dan kemudian gunakan context.fn(args)?
Di sini saya percaya anda juga telah memahami arahan
call
的原理,这里我简要还是说明一下原理,我也是参考JavaScript
panduan berwibawa dan kemudian melaksanakannya dengan kod.Mula-mula, mari kita lihat sintaks dan takrifan
call
, daripada versi Cina bagi spesifikasi ECMAScript:Mari kita berikan contoh mudah:
Kemudian lihat pada output selepas menggunakan
call
:Saya akan menjawab soalan anda di bawah berdasarkan buah berangan:
Pertama sekali, anda perlu memahami hubungan antara fungsi yang disimulasikan di atas dan pembolehubah dalam chestnut:
Perhatikan langkah ini, kami hanya meletakkan
jawil.sayHello
的引用地址给了lulin.sayHello
Ternyata
jawil.sayHello.call(context,arg1,arg2,arg3,arg4)
Potong cara anda
context
得到args=[arg1,arg2,arg3,arg4]
Kemudian laksanakan
lulin.sayHello([arg1,arg2,arg3,arg4])
Haha, ia sangat mengelirukan, bukan? Di sinilah letak masalahnya.Jadi bagaimana untuk menyelesaikan masalah ini? Ideanya adalah seperti di atas, masukkan semua parameter ke dalam rentetan, dan kemudian gunakan
eval
untuk melaksanakan.Kesan yang kami mahukan ialah
, ataululin.sayHello(arg1,arg2,arg3,arg4)
, keranalulin.sayHello
perlu menyusun semula parameter, anda tidak bolehlulin.sayHello(arg1,arg2,arg3,arg4)
这样的,因为lulin.sayHello
要重组参数,你不能拿到一个参数执行一次函数吧,或者把参数存到一起一次执行吧,唯一的想到的做法就是把所有参数拼成字符串,然后用eval
dapatkan satu Jalankan fungsi sekali dengan parametersimpan parameter bersama-sama dan laksanakannya sekali
untuk melaksanakan,lulin.sayHello([arg1,arg2,arg3,arg4])
,也不是lulin.sayHello(arg1)
,lulin.sayHello(arg2)
Satu-satunya cara yang terlintas di fikiran ialah meletakkan semua parameter ke dalam rentetan, dan kemudian gunakan.
Serupa dengan ini: "lulin.sayHello(arg1,arg2,arg3,arg4)" Ini adalah cara yang kita mahu, bukan, mahupun
Fungsilulin.sayHello(arg1)
,lulin.sayHello (arg2)
...eval
Apakah itu eval? Biar saya terangkan secara ringkas di sini.
eval() boleh mengira rentetan dan melaksanakan kod JavaScript di dalamnya.
eval(string)
Secara ringkasnya, ia menggunakan enjin penghuraian JavaScript untuk menghuraikan kandungan sekumpulan rentetan ini, anda boleh memahaminya dengan cara ini, anda meletakkan teg
eval
看成是.
Ia bersamaan dengan ini
Baiklah, mari kita lihat semula kod di atas Sebenarnya, masih terdapat masalah. Di bawah ialah kod penyahpepijatan lengkap:
Lihat output args:
["hujah[1]", "hujah[2]"]
Kemudian lihat pada output 'context.fn(' + args + ')':
"context.fn(arguments[1],arguments[2])"Bukankah ia agak mengelirukan
Malah, penukaran tersirat terlibat di sini:
Malah, ini bersamaan dengan'jawil'+[1,2]+[3,4]+3
sama dengan apa?'jawil'+[1,2]+[3,4]+3
等于多少?等于
"jawil1,23,43"
其实这个相当于
'jawil'+[1,2].toString()+[3,4].toString()+3
Sama dengan"jawil1,23,43"
'jawil'+[1,2].toString()+[3,4].toString( )+3Ruang adalah terhad, untuk penukaran yang lebih tersirat, sila rujuk artikel saya: Daripada ++[[]][+[]]+[+[]]==10? Penjelasan mendalam tentang penukaran tersirat dalam taip lemah JSBercakap tentang ini, saya telah mengatakan semua perkara yang anda boleh memahaminya sendiri. Penulis asal mungkin merujuk kepada orang lain ketika menulis ini ia dalam satu pukulan Nampaknya ia adalah perenggan yang sangat pendek. Kod ini sebenarnya mengandungi banyak mata pengetahuan.
args ialah tatasusunan,
context.fn(args)
hanya mempunyai satu parameter Dalam keadaan biasa, anda boleh menggunakan apply untuk menukar tatasusunan kepada parameter, tetapi di sini untuk mensimulasikan panggilan, menggunakan apply tidak bermakna. Jadi ia menggunakan toString() tatasusunan untuk memindahkan parameter selain daripada konteks ke context.fn.Kerana hujah[0] ialah konteks
Tidakkah anda nampak bahawa pembolehubah gelung bermula dari 1?