Saya berharap dapat mencari penjelasan yang jelas tentang perkara yang dilakukan oleh kata kunci "ini" dan cara menggunakannya dengan betul.
Nampaknya berkelakuan pelik dan saya tidak faham sepenuhnya mengapa.
this
Bagaimana ia berfungsi dan bila anda perlu menggunakannya?
Berbanding dengan bahasa lain,
this
关键字在 JavaScript 中的行为有所不同。在面向对象语言中,this
关键字指的是该类的当前实例。在 JavaScript 中,this
的值由函数的调用上下文 (context.function()
) dan kedudukan panggilannya ditentukan. p>1. Apabila digunakan dalam konteks global
Apabila anda menggunakannya dalam konteks global
this
时,它会绑定到全局对象(浏览器中的window
)Apabila anda menggunakan
this
时,this
di dalam fungsi yang ditakrifkan dalam konteks global anda masih terikat dengan objek global kerana fungsi itu sebenarnya adalah kaedah konteks global.Panggil pada objek
f1
是一个全局对象的方法。因此我们也可以在window
di atas, seperti ini:2. Apabila digunakan di dalam kaedah objek
Apabila anda menggunakan
this
关键字时,this
di dalam kaedah objek ia mengikat objek "terus" yang melampirkan.Saya telah meletakkan perkataan "segera" dalam petikan berganda di atas. Ini adalah untuk menunjukkan bahawa jika objek bersarang dalam objek lain,
this
terikat pada objek induk terdekat.Walaupun anda menambah fungsi sebagai kaedah pada objek secara eksplisit, ia masih mengikut peraturan di atas, iaitu
this
masih menunjuk kepada objek induk langsung.3. Apabila memanggil fungsi tanpa konteks
Digunakan
this
时,它会绑定到全局对象(浏览器中的window
) apabila anda memanggilnya di dalam fungsi tanpa sebarang konteks (iaitu bukan pada sebarang objek) (walaupun jika fungsi itu ditakrifkan di dalam objek).Cuba semua dengan fungsi
Kita juga boleh menggunakan fungsi untuk mencuba perkara di atas. Tetapi masih terdapat beberapa perbezaan.
this
. untuk menentukan mereka.new
dahulu.Di bawah saya mencuba semua yang saya lakukan di atas dengan Object dan
this
tetapi mula-mula mencipta fungsi dan bukannya menulis objek secara langsung.4. Apabila digunakan di dalam pembina .
Apabila fungsi digunakan sebagai pembina (iaitu, apabila dipanggil menggunakan kata kunci
new
关键字调用时),函数体内的this
), dalam badan fungsi menghala ke objek baharu yang sedang dibina.Jika kaedah berada pada rantai prototaip objek, maka
this
dalam kaedah merujuk kepada objek yang kaedah dipanggil, seolah-olah kaedah itu ditakrifkan pada objek itu.6. Fungsi panggilan dalaman(), apply() dan bind()
Function.prototype
.this
yang akan digunakan semasa melaksanakan fungsi. Mereka juga boleh menghantar sebarang hujah kepada fungsi asal apabila ia dipanggil.fun.apply(obj1 [, argsArray])
将obj1
设置为this
内的值code>fun() 并调用fun()
,传递argsArray
fun.apply(obj1 [, argsArray])fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
- 设置 obj1 作为fun()
内this
的值,并调用fun()
fun() , menghantar elemenargsArray
sebagai hujahnya.fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
- 返回对函数的引用fun
,其中 fun 内的this
绑定到obj1
,并且fun
的参数绑定到指定的参数arg1、arg2, arg3,...
- Tetapkan obj1 sebagaiapply
、call
和bind
之间的区别一定已经很明显了。apply
允许将参数指定为类似数组的对象,即具有数字length
属性和相应的非负整数属性的对象。而call
允许直接指定函数的参数。apply
和call
fun() menghantarthis
fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])fun
, di mana menyeronokkan ialah 🎜 terikat kepada 🎜obj1 dan hujah 🎜fun terikat kepada hujah yang ditentukan 🎜arg1, arg2, arg3,.... 🎜 🎜Kini, perbezaan antara 🎜apply, 🎜call dan 🎜bind mestilah jelas. 🎜apply membenarkan hujah ditentukan sebagai objek seperti tatasusunan, iaitu objek dengan sifat 🎜length angka dan sifat integer bukan negatif yang sepadan. Dan 🎜panggilan membolehkan parameter fungsi ditentukan secara langsung. Kedua-dua 🎜apply dan 🎜call segera panggil fungsi dalam konteks yang ditentukan dan dengan parameter yang ditentukan. bind, sebaliknya, hanya mengembalikan fungsi terikat kepada nilai dan argumen ini yang ditentukan. Kita boleh menangkap rujukan kepada fungsi yang dikembalikan ini dengan memberikannya kepada pembolehubah, yang kemudiannya boleh kita panggil pada bila-bila masa. 🎜 🎜 🎜🎜7. 🎜🎜🎜 di dalam pengendali acarathis
来引用相应的元素。这种直接的函数分配可以使用addeventListener
方法或通过onclick
terus dalam fungsi pengendali acara.)内使用
this
, ia merujuk kepada elementhis
会解析为全局对象window
digunakan secara tidak langsung melalui fungsi lain yang dipanggil dalam pengendali acara atau sifat acara.attachEvent
untuk melampirkan fungsi pada pengendali acara. Daripada memberikan fungsi kepada pengendali acara (dengan itu mencipta kaedah fungsi elemen), ia memanggil fungsi pada acara (dengan berkesan memanggilnya dalam konteks global).Saya syorkan JSFiddle中更好地尝试此操作>.
8.
dalam fungsi anak panah ES6this
Dalam fungsi anak panah,
fungsi yang mentakrifkan fungsi anak panah akan menjadithis
的行为类似于公共变量:它将从其词法范围继承。定义箭头函数的函数的this
将是箭头函数的this
berkelakuan seperti pembolehubah awam: ia akan diwarisi daripada skop leksikalnya.fungsi anak panah.
Jadi, ini adalah kelakuan yang sama seperti:
🎜Lihat kod di bawah: 🎜此
ialah kata kunci dalam JavaScript yang merupakan atribut konteks pelaksanaan. Penggunaan utamanya adalah dalam fungsi dan pembina.this
Peraturannya agak mudah (jika anda berpegang kepada amalan terbaik).Penerangan teknikal
this
dalam spesifikasiECMAScript standarddefinisi
this
melalui operasi abstrak (disingkatkan sebagai AO) ResolveThisBinding:Rekod persekitaran global, Rekod persekitaran modul, dan Rekod persekitaran fungsi masing-masing mempunyai kaedah GetThisBinding mereka sendiri.
GetThisEnvironment AO mencari LexicalEnvironment bagi konteks pelaksanaan menjalankan semasa dan mencari rekod persekitaran menaik yang paling hampir (dengan mengulangi sifat [[OuterEnv]]nya) yang mempunyai ini mengikat ini mengikat
ini. . Proses ini berakhir dengan satu daripada tiga jenis rekod persekitaran.
mod ketatthis
Nilai biasanya bergantung pada sama ada kod berada dalam.
GetThisBinding mencerminkan nilaithis
值,因此每当建立新的执行上下文时,this
Nilai pulangankonteks pelaksanaan semasa, jadi setiap kali konteks pelaksanaan baharu diwujudkan, akan menyelesaikan kepada nilai yang berbeza. Ini juga boleh berlaku apabila konteks pelaksanaan semasa diubah suai. Subseksyen berikut menyenaraikan lima senario di mana ini mungkin berlaku.
Anda boleh meletakkan sampel kod ke dalamAST Explorer
untuk mengikuti butiran spesifikasi.1. Konteks pelaksanaan global dalam skrip
dalam konteks global. Modul secara tersirat dalamIni ialah kod skrip yang dinilai di peringkat teratas, mis
GetThisBinding🎜 mengambil langkah berikut: 🎜this
Apabila dalam konteks pelaksanaan global awal skrip, menilai menyebabkanHarta [[GlobalThisValue]] rekod persekitaran global sentiasa ditetapkan kepada objek global yang ditentukan hos, boleh diakses melalui
globalThis
globalThis
(Web 上的 window
,Node.js 上的global
(tetingkapdi web
, Node.jsglobal
Dokumentasi di MDN). Ikuti langkah InitializeHostDefinedRealm untuk mengetahui cara sifat [[GlobalThisValue]] dijana.2. Konteks pelaksanaan global dalam modul
Modul telah diperkenalkan dalam ECMAScript 2015.
Ini berfungsi untuk modul cth.
Apabila dalam konteks pelaksanaan global awal modul, menilai内部时,而不是简单的
menyebabkan
Dalam modul, nilaithis
GetThisBinding mengambil langkah berikut:sentiasatidak ditentukan
this
的值在全局上下文中始终是未定义
mod ketat.evalkod
Terdapat dua jenispanggilan:
eval
langsungdan tidak langsung. Perbezaan ini telah wujud sejak edisi kelima ECMAScript.eval
调用通常类似于eval(
...);
或(eval)(
...); (或((eval))(
…);
dll.). 1 Ini hanya langsung (jika ungkapan panggilan menepati corak sempit). 2eval
调用涉及以任何其他方式调用函数引用eval
。它可以是eval?.(
...)
,(
..., eval)(
...),
,调用window.eval(
...)
,eval.call(
...,
...)给定 const aliasEval1 = eval; 等。 window.aliasEval2 = eval;
,也可以是aliasEval1(
…)
、aliasEval2(
…)
代码>.分别给出 const originalEval = eval; window.eval = (x) => originalEval(x);eval(
…)
juga tidak langsung.Lihat jawapan chuckj untuk "(1, eval)('this') vs eval('this') dalam JavaScript?" dan Dmitry Soshnikov ECMA-262- 5 butiran – Bab 2: Mod Ketat (Arkib), untuk kes di mana anda mungkin menggunakan panggilan
eval()
tidak langsung.PerformEval melaksanakan kod
rekod persekitaran deklaratifeval
代码。它创建一个新的 声明性环境记录 作为其 LexicalEnvironment,这是 GetThisEnvironment 从中获取this
eval. Ia menciptabaharu sebagai LexicalEnvironmentnya, iaitu GetThisEnvironment
Kemudian, jikathis
出现在eval
untuk mendapatkan ini daripada > nilai.dalam kod, GetThisEnvironment dipanggil dan nilainya dikembalikan.
rekod persekitaran deklaratifdicipta
bergantung pada sama ada panggilan- eval adalah secara langsung atau tidak langsung:
- Dalam penilaian langsung, ia akan berdasarkan konteks pelaksanaan yang sedang berjalanpersekitaran leksikal semasa.
Dalam penilaian tidak langsung, ia akan berdasarkan atribut [[GlobalEnv]] (李>rekod persekitaran global
daripadarekod alam
yang melaksanakan penilaian tidak langsung). 🎜 🎜 🎜Ini bermaksud: 🎜this
值不会改变;它取自名为eval
.this
值是全局对象 (globalThis
).新函数
怎么样? —new Function
与eval
Serupa, tetapi ia tidak memanggil kod dengan serta-merta; ini Pengikatan tidak terpakai di mana-mana di sini kecuali apabila memanggil fungsi, yang berfungsi dengan baik seperti yang diterangkan dalam subseksyen seterusnya.4. Masukkan fungsikod
Masukkan kod fungsi apabila memanggil fungsi .
Terdapat empat kategori sintaks untuk fungsi panggilan.
Panggilan fungsi sebenar berlaku di Panggilan AO, yang ditentukan oleh konteks panggilan menggunakan ThisValue parameter ini diluluskan dalam senarai panjang panggilan yang berkaitan dengan panggilan. Panggil memanggil [[Panggil]] slot dalaman fungsi. Ini memanggil PrepareForOrdinaryCall, di mana rekod persekitaran fungsi baharu telah dibuat:
Selain itu, terdapat juga medan [[ThisValue]] dalam rekod persekitaran fungsi:
PanggilanNewFunctionEnvironment juga menetapkan sifat [[ThisBindingStatus]] bagi persekitaran fungsi.
[[Panggil]] juga memanggil OrdinaryCallBindThis, di mana thisArgument yang sesuai ditentukan berdasarkan:
Selepas pengesahan, kaedah BindThisValue rekod persekitaran fungsi yang baru dicipta akhirnya dipanggil untuk benar-benar menetapkan medan [[ThisValue]] untuk ditambahkan pada thisArgument.
Akhir sekali, medan ini ialah rekod persekitaran fungsi GetThisBinding AO mendapat nilai
this
dari lokasi berikut:Sekali lagi, penentuan tepat nilai ini bergantung kepada banyak faktor; ini hanyalah gambaran umum. Dengan latar belakang teknikal ini, mari kita lihat semua contoh konkrit.
Fungsi anak panah
Apabila mengira fungsi anak panah, sifat objek fungsi slot dalaman [[ThisMode]] ditetapkan kepada "leksikal" dalam OrdinaryFunctionCreate. p>
Di OrdinaryCallBindThis ia memerlukan fungsi F:
Ini hanya bermakna bahawa baki algoritma yang mengikat ini dilangkau. Fungsi anak panah tidak mengikat nilai ini mereka sendiri.
Jadi, apakah
this
dalam fungsi anak panah? Untuk menyemak ResolveThisBinding dan GetThisEnvironment, kaedah HasThisBinding secara eksplisit mengembalikan false.Jadi kami secara berulang mencari persekitaran luaran. Proses ini akan berakhir dalam satu daripada tiga persekitaran dengan pengikatan ini.
Ini hanya bermaksud bahawa, dalam badan fungsi anak panah,
this
berasal daripada skop leksikal fungsi anak panah , atau dengan kata lain (dari Fungsi anak panah vs. pengisytiharan/ungkapan fungsi: adakah ia setara/komutatif? ):FungsiSifat
Dalam fungsi biasa (
.fungsi
, kaedahfunction
、方法),this
) , ditentukan oleh kaedah panggilan fungsiDalam mana-mana panggilan fungsi berikut,
func
内的this
值将为refObj
. 1refObj.func()
refObj["func"]()
refObj?.func()
refObj.func?.()
refObj.func``
Jika fungsi yang dipanggil secara sintaksis adalah sifat objek asas, maka objek asas itu akan menjadi "rujukan" panggilan, yang dalam kes biasa ialah nilai
(atauthis
的值。上面链接的评估步骤对此进行了解释;例如,在refObj.func()
(或refObj["func"]()
)中,CallMemberExpression 是整个表达式refObj.func()
,它由 MemberExpressionrefObj.func
和 参数()
ini. Langkah penilaian yang dipautkan di atas menerangkan perkara ini; contohnya, dalam),
refObj.func
和refObj
CallMemberExpressionialah Seluruh ungkapan- , yang terdiri daripada
MemberExpression-
- refObj.func dan
parameter
refObj.func
作为值是可调用的函数对象;相应的引用用于确定this
().Selain itu,
Mereka semua adalah ungkapan,?.()
之前、``
memainkan tiga peranan: 代码>Semuanya adalah rujukan, dan Semuanya adalah nilai.
ataurefObj.func
时为refObj
;或foo.bar
code> 当应用于foo.bar.baz
Mengikat. Pautan pilihan dan contoh templat teg berfungsi sangat serupa: pada asasnya, rujukan didahului dengan().
EvaluateCallthis
。简单属性不会影响执行上下文,例如这里,this
menggunakan IsPropertyReference
akan mendapatkan harta [[Base]] ini dan menggunakannya sebagai nilaiuntuk menentukan sama ada ia secara sintaksis merupakan sifat objek. Ia cuba mendapatkan atribut [[Base]] rujukan (cth. apabila digunakan pada ). Jika anda menulisnya sebagai harta,
GetThisValuethis
.Nota: Cara Penetap/Penetap berfungsi, berkenaan dalam skop global:
🎜tanpa rujukan asas, mod ketat dan 🎜🎜dengan🎜🎜🎜 🎜Panggilan tanpa rujukan asas biasanya merupakan fungsi yang tidak dipanggil sebagai atribut. Contohnya: 🎜 🎜Ini juga berlaku apabila 🎜lulus atau menetapkan kaedah🎜, atau apabila menggunakan 🎜 pengendali koma🎜. Di sinilah perbezaan antara rekod rujukan dan nilai adalah relevan. 🎜Perhatikan bahawa fungsi
j
:按照规范,您会注意到j
只能返回函数对象(Value)本身,而不能返回引用记录。因此,基本引用refObj
tiada.EvaluateCall panggilan panggilan, di mana thisValue adalah undefined. Ini berbeza dalam OrdinaryCallBindThis (F: fungsi objek; thisArgument: thisValue dihantar ke Panggil):
Nota: Langkah 5 menetapkan nilai sebenar
Argumen inithis
的实际值设置为严格模式下提供的 thisArgument - 在本例中为undefined
。在“草率模式”下,未定义或 null thisArgument 会导致this
kepada thisArgument yang disediakan dalam mod ketat - dalam kes ini,undefined
. Dalam "mod ceroboh", tidak ditentukan atau batalmenyebabkan menjadi nilai ini global. Jika IsPropertyReference
mengembalikanfalse, maka EvaluateCall mengambil langkah berikut: Ini tidak ditentukan Nilai ini Boleh datang daripada: refEnv sec-with-statement-runtime-semantics-evaluation" rel="noreferrer">Symbol.unscopables
dan:. Dalam kes ini, thisValue
Symbol.unscopables
(MDN 上的文档)来控制with
akan menjadi objek pengikat.Juga
( Dokumentasi tentang MDN
) untuk mengawalkelakuan yang mengikat.
this
Untuk meringkaskan, setakat ini:Perhatikan bahawa apabila mengira
.call
,.apply
,.bind
ia tidak penting di mana fungsi normal ditakrifkan.
OrdinaryCallBindThis🎜, tidak seperti langkah 6.2 (dalam spesifikasi), ialah nilai 🎜ini🎜 asal berada dalam mod "ceroboh" 🎜 sahaja 🎜 dilemparkan ke objek. 🎜.call
,.apply
,.bind
, thisArg dan primitif Satu lagi akibat daripada langkah 5Untuk menyemak ini, mari perkenalkan satu lagi sumber nilai ini: tiga kaedah yang mengatasi pengikatan ini: 4
Function.prototype.apply(thisArg, argArray)
Function.prototype.
{调用
,绑定
}(thisArg, ...args)
李>.bind 创建一个绑定函数,其this 绑定已设置为 thisArg 并且无法再次更改。
Panggil fungsi dengan segera dan tetapkan.bind
.call
和.apply
mencipta fungsi mengikat yang pengikatan ini sudah ditetapkan kepada Arg ini dan tidak boleh ditukar lagi..call
dan.apply
ini
, Gunakan.call
和.apply
直接映射到 Call ,使用指定的thisArg。.bind
untuk terikat kepada Arg ini..call
dan.apply
peta terus ke PanggilthisArg yang dinyatakan.
untuk mencipta fungsi terikat. Mereka mempunyai kaedah.bind
Gunakan BoundFunctionCreate[[Panggil ]] sendiri
, yang mencari slot dalaman [[BoundThis]] bagi objek fungsi.ini
Object("s")
或new String("s")
: Untuk objek, ini adalah sama dalam mod ketat dan tidak ketat.Sekarang, cuba berikan nilai mentah:
Dalam mod tidak ketat, primitif dipaksa ke bentuk pembalut objeknya. Ia adalah jenis objek yang sama yang anda dapat semasa memanggilthis
. Dalam mod ketat anda boleh menggunakan primitif:
新
Perpustakaan yang menggunakan kaedah ini seperti set jQuery ke elemen DOM yang dipilih di sini:Pembina,
dan 🎜🎜🎜🎜 🎜Apabila memanggil fungsi sebagai pembina menggunakan operatornew
运算符将函数作为构造函数调用时,EvaluateNew 调用 Construct,它调用 [[Construct]] 方法。如果函数是基本构造函数(即不是class extends
...{
...}
),它会设置 thisArgument到从构造函数的原型创建的新对象。构造函数中this
上设置的属性最终将出现在生成的实例对象上。this
Kelasbaharu
, EvaluateNew ialah dipanggil Construct🎜, yang memanggil kaedah [[Construct]] 🎜. Jika fungsi itu ialah pembina asas (iaitu bukanclass extends
...{
...}
), ia akan menetapkan 🎜thisArgument🎜 kepada nilai daripada Objek baru yang dicipta oleh prototaip pembina. Sifat yang ditetapkan pada 🎜 dalam pembina akhirnya akan muncul pada objek contoh yang dijana. 🎜 dikembalikan secara tersirat melainkan anda secara eksplisit mengembalikan nilai bukan primitif anda sendiri. 🎜class
ialah cara baharu mencipta pembina, yang diperkenalkan dalam ECMAScript 2015.Takrifan kelas secara tersirat dalam mod ketat:
超级
H4>new
行为的例外是class extends
...{
...}
,如上所述。派生类在调用时不会立即设置其 this 值;它们只有在通过一系列super
调用到达基类后才会这样做(在没有自己的构造函数
的情况下隐式发生)。不允许在调用super
之前使用this
.Panggilsuper 调用具有调用的词法范围(函数环境记录)的 this 值的超级构造函数。 GetThisValue 对于
inisuper
super
调用有一个特殊的规则。它使用 BindThisValue 将this
Memanggil super constructor dengan nilaidaripada skop leksikal (rekod persekitaran fungsi) panggilan. GetThisValue
Terdapat peraturan khas untuk panggilansuper
. Ia menggunakan BindThisValueuntuk menetapkan
kepada rekod persekitaran tersebut.class
5. Medan kelas penilaian Medan contoh dan medan statik telah diperkenalkan dalam ECMAScript 2022. Apabila menilai , ClassDefinitionEvaluation dilaksanakan, mengubah suai konteks pelaksanaan yang sedang berjalan. Untuk setiapthis
this
#x
Jika medan tidak statik,Medan peribadi (cth. ) dan kaedah ditambahkan pada persekitaran peribadi.
Blok Statikthis
adalah cadangan
. Blok statik berfungsi dengan cara yang sama seperti medan dan kaedah statik: 🎜 di dalamnya merujuk kepada kelas itu sendiri. 🎜 🎜Perhatikan bahawa dalam kaedah dan getter/setter, 🎜 berfungsi sama seperti dalam sifat fungsi biasa. 🎜this
TC39 Fasa 31:
(o.f)()
等价于o.f()
;(f)()
相当于f()
. Artikel 2ality ini (Arkib). Lihat terutamanya Cara menilai ParenthesizedExpression.2: Ia mestilah MemberExpression em>, tidak boleh menjadi harta, mesti mempunyai [[ReferencedName]] dengan tepat "eval", dan mestilah objek intrinsik %eval%.
3: Setiap kali spesifikasi mengatakan "biar ref menjadi hasil menilai X", X ialah beberapa ungkapan yang langkah penilaiannya perlu anda cari. Contohnya, menilai MemberExpression atau CallExpression ialah algoritma ini. Sebahagian daripada mereka menjana rekod rujukan.
4: Terdapat beberapa kaedah asli dan hos lain yang membenarkan menyediakan nilai ini, terutamanya
MDNArray.prototype.map
,Array.prototype.forEach
, dsb. MenerimaArray.prototype.map
、Array.prototype.forEach 等接受 thisArg 作为第二个参数。任何人都可以创建自己的方法来更改this
,例如(func, thisArg) => func.bind(thisArg)
、(func, thisArg) => func。 call(thisArg)
Arg ini sebagai hujah kedua. Sesiapa sahaja boleh mencipta kaedah mereka sendiri untuk menukar , seperti(func, thisArg) => func.bind(thisArg)
,(func, thisArg) => func. call(thisArg)
dsb. Seperti biasa,menyediakan dokumentasi perkhidmatan yang hebat.
Hanya untuk keseronokan, uji pemahaman anda dengan beberapa contoh
pada baris yang ditanda? Mengapa?"this
Untuk setiap coretan kod, jawab soalan berikut: "Apakah nilaiUntuk mendedahkan jawapan, klik pada kotak kelabu.