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 this
akan dicatat sebagai window
. Ini karena window
merupakan variabel global dalam cakupan browser web.
Jika Anda menjalankan bagian kode yang sama di lingkungan seperti node.js, this
akan merujuk ke variabel global di aplikasi Anda.
Sekarang jika kita menjalankan ini dalam mode ketat dengan menambahkan pernyataan "use strict";
ke awal deklarasi fungsi, this
tidak akan lagi merujuk ke variabel global di salah satu lingkungan. Ini dilakukan untuk menghindari kebingungan dalam mode ketat. this
akan, 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 forEach
dan slice
, Anda harus sudah tahu bahwa this
variabel dalam kasus itu merujuk Object
pada yang Anda panggil fungsi itu (Perhatikan bahwa dalam javascript, hampir semua adalah Object
, termasuk Array
s dan Function
s). 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 Object
berisi properti yang menyimpan a Function
, properti itu disebut metode. Metode ini, ketika dipanggil, akan selalu memiliki this
set variabel untuk Object
dikaitkan 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 this
tidak 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 new
kunci
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 new
kata kunci.
- Memanggil fungsi dengan
new
kata kunci akan segera menginisialisasi Object
tipe Person
.
- Konstruktor ini
Object
mengatur konstruktornya Person
. Juga, perhatikan bahwa hanya typeof awal
akan kembali Object
.
- Ini baru
Object
akan diberi prototipe Person.prototype
. Ini berarti bahwa setiap metode atau properti dalam Person
prototipe akan tersedia untuk semua kejadian Person
, termasuk awal
.
- Fungsi
Person
itu sendiri sekarang dipanggil; this
menjadi referensi ke objek yang baru dibangun awal
.
Cukup mudah, eh?
Perhatikan bahwa spesifikasi ECMAScript resmi tidak menyatakan bahwa jenis fungsi tersebut adalah constructor
fungsi sebenarnya . Mereka hanya fungsi normal, dan new
dapat digunakan pada fungsi apa pun. Hanya saja kami menggunakannya seperti itu, dan kami menyebutnya begitu saja.
Memanggil fungsi pada Fungsi: call
danapply
Jadi ya, karena function
s 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 call
dan apply
, dan keduanya dapat digunakan untuk memanipulasi nilai this
dalam 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 this
fungsi foo
sebagai referensi thisArg
. Semua parameter lain yang diteruskan ke call
diteruskan ke fungsi foo
sebagai argumen.
Jadi kode di atas akan masuk {myObj: "is cool"}, [1, 2, 3]
konsol. Cara yang cukup bagus untuk mengubah nilai this
dalam fungsi apa pun.
apply
hampir sama dengan call
accept yang hanya membutuhkan dua parameter: thisArg
dan array yang berisi argumen untuk diteruskan ke fungsi. Jadi call
panggilan di atas dapat diterjemahkan menjadi apply
seperti ini:
foo.apply(thisArg, [1,2,3])
Catat itu call
dan apply
dapat menimpa nilai this
set oleh metode titik yang kita bahas dalam butir kedua. Cukup sederhana :)
Mempresentasikan .... bind
!
bind
adalah saudara dari call
dan apply
. Ini juga merupakan metode yang diwarisi oleh semua fungsi dari Function
konstruktor global di Javascript. Perbedaan antara bind
dan call
/ apply
adalah keduanya call
dan apply
akan benar-benar memanggil fungsi. bind
, di sisi lain, mengembalikan fungsi baru dengan thisArg
dan arguments
sebelumnya. 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 call
dan apply
, bind
juga akan menunggangi nilai this
set oleh metode dot-method.
Perhatikan juga bahwa tidak satu pun dari ketiga fungsi ini melakukan perubahan pada fungsi aslinya. call
dan apply
akan mengembalikan nilai dari fungsi yang baru dibangun sementara bind
akan mengembalikan fungsi yang baru dibangun itu sendiri, siap dipanggil.
Barang ekstra, salin ini
Terkadang, Anda tidak suka fakta yang this
berubah 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 this
berubah dengan cakupan bersarang, tetapi kami menginginkan nilai dari this
lingkup asli. Jadi kami 'menyalin' this
ke that
dan menggunakan salinannya sebagai ganti this
. Pintar, eh?
Indeks:
- Apa yang ditahan
this
secara default?
- Bagaimana jika kita memanggil fungsi sebagai metode dengan notasi Object-dot?
- Bagaimana jika kita menggunakan
new
kata kunci?
- Bagaimana cara kita memanipulasi
this
dengan call
dan apply
?
- Menggunakan
bind
.
- Menyalin
this
untuk memecahkan masalah ruang lingkup bersarang.