Javascript this
Doa fungsi sederhana
Pertimbangkan fungsi berikut:
function foo() {
console.log("bar");
console.log(this);
}
foo(); // calling the function
Perhatikan bahwa kami menjalankan ini dalam mode normal, yaitu mode ketat tidak digunakan.
Saat berjalan di browser, nilai thisakan dicatat sebagai window. Ini karena windowmerupakan variabel global dalam cakupan browser web.
Jika Anda menjalankan bagian kode yang sama di lingkungan seperti node.js, thisakan merujuk ke variabel global di aplikasi Anda.
Sekarang jika kita menjalankan ini dalam mode ketat dengan menambahkan pernyataan "use strict";ke awal deklarasi fungsi, thistidak akan lagi merujuk ke variabel global di salah satu lingkungan. Ini dilakukan untuk menghindari kebingungan dalam mode ketat. thisakan, dalam hal ini hanya login undefined, karena memang seperti itu, tidak didefinisikan.
Dalam kasus berikut, kita akan melihat bagaimana memanipulasi nilai this.
Memanggil fungsi pada objek
Ada berbagai cara untuk melakukan ini. Jika Anda telah memanggil metode asli dalam Javascript seperti forEachdan slice, Anda harus sudah tahu bahwa thisvariabel dalam kasus itu merujuk Objectpada yang Anda panggil fungsi itu (Perhatikan bahwa dalam javascript, hampir semua adalah Object, termasuk Arrays dan Functions). Ambil kode berikut sebagai contoh.
var myObj = {key: "Obj"};
myObj.logThis = function () {
// I am a method
console.log(this);
}
myObj.logThis(); // myObj is logged
Jika suatu Objectberisi properti yang menyimpan a Function, properti itu disebut metode. Metode ini, ketika dipanggil, akan selalu memiliki thisset variabel untuk Objectdikaitkan dengan itu. Ini berlaku untuk mode ketat dan non-ketat.
Perhatikan bahwa jika suatu metode disimpan (atau lebih tepatnya, disalin) dalam variabel lain, referensi ke thistidak lagi dipertahankan dalam variabel baru. Sebagai contoh:
// continuing with the previous code snippet
var myVar = myObj.logThis;
myVar();
// logs either of window/global/undefined based on mode of operation
Mempertimbangkan skenario yang lebih umum:
var el = document.getElementById('idOfEl');
el.addEventListener('click', function() { console.log(this) });
// the function called by addEventListener contains this as the reference to the element
// so clicking on our element would log that element itself
Kata newkunci
Pertimbangkan fungsi konstruktor dalam Javascript:
function Person (name) {
this.name = name;
this.sayHello = function () {
console.log ("Hello", this);
}
}
var awal = new Person("Awal");
awal.sayHello();
// In `awal.sayHello`, `this` contains the reference to the variable `awal`
Bagaimana cara kerjanya? Baiklah, mari kita lihat apa yang terjadi ketika kita menggunakan newkata kunci.
- Memanggil fungsi dengan
newkata kunci akan segera menginisialisasi Objecttipe Person.
- Konstruktor ini
Objectmengatur konstruktornya Person. Juga, perhatikan bahwa hanya typeof awalakan kembali Object.
- Ini baru
Objectakan diberi prototipe Person.prototype. Ini berarti bahwa setiap metode atau properti dalam Personprototipe akan tersedia untuk semua kejadian Person, termasuk awal.
- Fungsi
Personitu sendiri sekarang dipanggil; thismenjadi referensi ke objek yang baru dibangun awal.
Cukup mudah, eh?
Perhatikan bahwa spesifikasi ECMAScript resmi tidak menyatakan bahwa jenis fungsi tersebut adalah constructorfungsi sebenarnya . Mereka hanya fungsi normal, dan newdapat digunakan pada fungsi apa pun. Hanya saja kami menggunakannya seperti itu, dan kami menyebutnya begitu saja.
Memanggil fungsi pada Fungsi: calldanapply
Jadi ya, karena functions juga Objects(dan sebenarnya variabel kelas pertama dalam Javascript), bahkan fungsi memiliki metode yang ... yah, fungsi itu sendiri.
Semua fungsi mewarisi dari global Function, dan dua dari banyak metodenya adalah calldan apply, dan keduanya dapat digunakan untuk memanipulasi nilai thisdalam fungsi yang mereka panggil.
function foo () { console.log (this, arguments); }
var thisArg = {myObj: "is cool"};
foo.call(thisArg, 1, 2, 3);
Ini adalah contoh khas penggunaan call. Ini pada dasarnya mengambil parameter pertama dan menetapkan thisfungsi foosebagai referensi thisArg. Semua parameter lain yang diteruskan ke callditeruskan ke fungsi foosebagai argumen.
Jadi kode di atas akan masuk {myObj: "is cool"}, [1, 2, 3]konsol. Cara yang cukup bagus untuk mengubah nilai thisdalam fungsi apa pun.
applyhampir sama dengan callaccept yang hanya membutuhkan dua parameter: thisArgdan array yang berisi argumen untuk diteruskan ke fungsi. Jadi callpanggilan di atas dapat diterjemahkan menjadi applyseperti ini:
foo.apply(thisArg, [1,2,3])
Catat itu calldan applydapat menimpa nilai thisset oleh metode titik yang kita bahas dalam butir kedua. Cukup sederhana :)
Mempresentasikan .... bind!
bindadalah saudara dari calldan apply. Ini juga merupakan metode yang diwarisi oleh semua fungsi dari Functionkonstruktor global di Javascript. Perbedaan antara binddan call/ applyadalah keduanya calldan applyakan benar-benar memanggil fungsi. bind, di sisi lain, mengembalikan fungsi baru dengan thisArgdan argumentssebelumnya. Mari kita ambil contoh untuk lebih memahami ini:
function foo (a, b) {
console.log (this, arguments);
}
var thisArg = {myObj: "even more cool now"};
var bound = foo.bind(thisArg, 1, 2);
console.log (typeof bound); // logs `function`
console.log (bound);
/* logs `function () { native code }` */
bound(); // calling the function returned by `.bind`
// logs `{myObj: "even more cool now"}, [1, 2]`
Lihat perbedaan antara ketiganya? Itu halus, tetapi mereka digunakan secara berbeda. Sukai calldan apply, bindjuga akan menunggangi nilai thisset oleh metode dot-method.
Perhatikan juga bahwa tidak satu pun dari ketiga fungsi ini melakukan perubahan pada fungsi aslinya. calldan applyakan mengembalikan nilai dari fungsi yang baru dibangun sementara bindakan mengembalikan fungsi yang baru dibangun itu sendiri, siap dipanggil.
Barang ekstra, salin ini
Terkadang, Anda tidak suka fakta yang thisberubah dengan cakupan, terutama cakupan bersarang. Lihatlah contoh berikut.
var myObj = {
hello: function () {
return "world"
},
myMethod: function () {
// copy this, variable names are case-sensitive
var that = this;
// callbacks ftw \o/
foo.bar("args", function () {
// I want to call `hello` here
this.hello(); // error
// but `this` references to `foo` damn!
// oh wait we have a backup \o/
that.hello(); // "world"
});
}
};
Dalam kode di atas, kita melihat bahwa nilai thisberubah dengan cakupan bersarang, tetapi kami menginginkan nilai dari thislingkup asli. Jadi kami 'menyalin' thiske thatdan menggunakan salinannya sebagai ganti this. Pintar, eh?
Indeks:
- Apa yang ditahan
thissecara default?
- Bagaimana jika kita memanggil fungsi sebagai metode dengan notasi Object-dot?
- Bagaimana jika kita menggunakan
newkata kunci?
- Bagaimana cara kita memanipulasi
thisdengan calldan apply?
- Menggunakan
bind.
- Menyalin
thisuntuk memecahkan masalah ruang lingkup bersarang.