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)?
認證高級PHP講師
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:
var jawil = {
name: "jawil",
sayHello: function (age) {
console.log("hello, i am ", this.name + " " + age + " years old");
}
};
var lulin = {
name: "lulin",
};
jawil.sayHello(24);
// hello, i am jawil 24 years old
Kemudian lihat pada output selepas menggunakan call
:
jawil.sayHello.call(lulin, 24);// hello, i am lulin 24 years old
Saya akan menjawab soalan anda di bawah berdasarkan buah berangan:
adalah untuk mensimulasikan pelaksanaan
call
的實現(xiàn),請問為什么要push一個字符串,下面再用eva
l?直接傳入arguments[i]
,然后下面用context.fn(args)
Mengapa anda perlu menolak rentetan dan menggunakaneva
l seterusnya? Hantarkanarguments[i]
secara langsung, kemudian gunakancontext.fn(args)
mengapa tidak?
Pertama sekali, anda perlu memahami hubungan antara fungsi yang disimulasikan di atas dan pembolehubah dalam chestnut:
context => lulin
context.fn => jawil.sayHello
Perhatikan langkah ini, kami hanya meletakkan jawil.sayHello
的引用地址給了lulin.sayHello
Ternyata jawil.sayHello.call(context,arg1,arg2,arg3,arg4)
Potong cara andacontext
得到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 lulin.sayHello(arg1,arg2,arg3,arg4)
, kerana lulin.sayHello
perlu menyusun semula parameter, anda tidak boleh lulin.sayHello(arg1,arg2,arg3,arg4)
這樣的,因為lulin.sayHello
要重組參數(shù),你不能拿到一個參數(shù)執(zhí)行一次函數(shù)吧,或者把參數(shù)存到一起一次執(zhí)行吧,唯一的想到的做法就是把所有參數(shù)拼成字符串,然后用eval
dapatkan satu Jalankan fungsi sekali dengan parameter
simpan parameter bersama-sama dan laksanakannya sekali 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 lulin.sayHello(arg1)
,lulin.sayHello (arg2)
...eval
Apakah itu eval? Biar saya terangkan secara ringkas di sini.
Mari kita lihat secara ringkasFungsifungsi
definisi dan penggunaan
eval() boleh mengira rentetan dan melaksanakan kod JavaScript di dalamnya. eval(string)
Tatabahasa:?? ???? rentetan diperlukan. Rentetan untuk menilai yang mengandungi ungkapan JavaScript untuk dinilai atau pernyataan untuk dilaksanakan. Kaedah ini hanya menerima rentetan mentah sebagai parameter, jika parameter rentetan bukan rentetan mentah, maka kaedah itu akan kembali tidak berubah. Oleh itu, jangan berikan objek String sebagai argumen kepada fungsi eval(). ??
Secara ringkasnya, ia menggunakan enjin penghuraian JavaScript untuk menghuraikan kandungan sekumpulan rentetan ini, anda boleh memahaminya dengan cara ini, anda meletakkan teg eval
看成是<script>
.
eval('function Test(a,b,c,d){console.log(a,b,c,d)};
Test(1,2,3,4)')
Ia bersamaan dengan ini
<script>
function Test(a,b,c,d){
console.log(a,b,c,d)
};
Test(1,2,3,4)
</script>
Baiklah, mari kita lihat semula kod di atas Sebenarnya, masih terdapat masalah. Di bawah ialah kod penyahpepijatan lengkap:
Function.prototype.call2 = function(context) {
context.fn = this;
var args = [];
for (var i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + ']');
}
console.log(args)
var star = 'context.fn(' + args + ')'
console.log(star)
eval('context.fn(' + args + ')');
delete context.fn;
}
var jawil = {
name: "jawil",
sayHello: function(age) {
console.log("hello, i am ", this.name + " " + age + " years old");
}
};
var lulin = {
name: "lulin",
};
jawil.sayHello.call2(lulin, 24, 25);
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:
'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( )+3
Ruang adalah terhad, untuk penukaran yang lebih tersirat, sila rujuk artikel saya: Daripada ++[[]][+[]]+[+[]]==10? Penjelasan mendalam tentang penukaran tersirat dalam taip lemah JS
Bercakap 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?