Bahkan, ini adalah masalah klise. Ada banyak artikel tentang ini. Sebenarnya, saya pikir saya sudah mengetahuinya, tetapi kemarin, saya masih memiliki sedikit keraguan selama proyek. Saya berpikir tentang artikel terperinci yang telah saya kumpulkan dan baca di Javascript Weekly (ada tautan kemudian, dan terjemahan bahasa Mandarin tentang tanah jarang dilampirkan) dan artikel lain yang direkomendasikan oleh senior, jadi saya melihat mereka dan pemahaman saya tentang hal ini memang sedikit meningkat.
'Ini' dalam JavaScript adalah dinamis dan ditentukan ketika fungsi dijalankan, bukan saat fungsi dinyatakan. Semua fungsi dapat memanggil 'ini', yang tidak masalah jika fungsi tersebut milik suatu objek. Mengenai ini, terutama ada empat situasi.
1. Metode yang digunakan sebagai objek disebut
Jika fungsi adalah metode yang dianggap sebagai objek, maka fungsi ini menunjuk ke objek;
var John = {firstName: "John"} func func () {waspada (this.firstname + ": hai!")} John.sayhi = func John.sayhi () // this = JohnAda sesuatu yang patut dicatat di sini. Ketika metode objek diambil dan ditugaskan ke variabel, metode ini menjadi pemicu fungsi, dan ini menunjuk ke jendela atau underfind (mode ketat).
2. Panggilan dalam fungsi
Ketika fungsi ini memiliki ini, itu sebenarnya berarti disebut sebagai metode. Memanggil antara keduanya setara dengan memperlakukannya sebagai objek jendela. Ini menunjuk ke jendela. Perlu dicatat bahwa ES5 benar -benar menetapkan bahwa ini = tidak terdefinisi, dan hanya browser yang masih dieksekusi sesuai dengan metode lama (saya mengujinya dalam versi terbaru Chrome, Safari, dan Firefox semuanya menunjuk ke Window (201607)), dan menggunakan mode yang ketat untuk menunjuk untuk tidak terdefinisi di bawah Firefox;
func () funce func () {waspada (this) // [jendela objek] atau [objek global] atau jenis ..}Untuk lulus ini, () harus menjadi tipe referensi sebelumnya, mirip dengan obj.a atau obj ['a'], dan tidak bisa apa pun.
Ada juga lubang kecil di sini. Ketika ada fungsi dalam metode objek, fungsi sebenarnya dipicu sebagai mode fungsi, sehingga default ke jendela ini (tidak terdefinisi dalam mode ketat). Solusinya adalah mengikat ini ke fungsi.
var number = {numberA: 5, numberb: 10, sum: function () {console.log (this === number); // => Fungsi True Calculate () {// Ini adalah jendela atau tidak terdefinisi dalam mode ketat Console.log (ini === angka); // => false return this.numbera + this.numberb; } return calculate (); }}; numbers.sum (); // => nan atau melempar typeError dalam mode ketat var angka = {angka: 5, angkab: 10, sum: function () {console.log (this === angka); // => Fungsi True Calculate () {Console.log (ini === Numbers); // => true return this.numbera + this.numberb; } // Gunakan metode .call () untuk memodifikasi konteks konteks calculate.call (ini); }}; numbers.sum (); // => 153. Hubungi baru
Variabel yang merujuk suatu objek sebenarnya menyimpan referensi ke objek, yaitu, variabel sebenarnya menyimpan pointer ke data nyata.
Saat menggunakan kata kunci baru, perubahan ini benar -benar mengambil langkah -langkah berikut:
Buat ini = {}.
Ini dapat diubah selama pelaksanaan atribut baru, dan kemudian ditambahkan;
Mengembalikan ini berubah.
fungsi hewan (nama) {this.name = name this.canwalk = true} var hewan = hewan baru ("beastie") alert (hewan.name)Perlu dicatat bahwa jika konstruktor mengembalikan objek, maka ini menunjuk ke objek yang dikembalikan;
fungsi hewan () {this.name = 'mousie'; this.age = '18'; return {name: 'godzilla'} // <- akan dikembalikan} var hewan = hewan baru () console.log (hewan.Penting untuk dicatat di sini yang tidak lupa menggunakan yang baru, jika tidak fungsi baru tidak akan dibuat. Sebaliknya, itu hanya mengeksekusi fungsi, yang setara dengan panggilan fungsi, dan ini sebenarnya menunjuk ke jendela
function vehicle (type, wheelscount) {this.type = type; this.wheelscount = wheelscount; kembalikan ini;} // fungsi InvocationVar car = kendaraan ('mobil', 4); car.type; // => 'car' car.wheelscount // => 4 car === window // => true4. Jelas Sebut Ini, Gunakan Panggilan dan Terapkan
Ini adalah tempat yang paling terinspirasi JavaScript.
Kode berikut:
func.call(obj, arg1, arg2,...)
Parameter pertama akan digunakan sebagai objek referensi dari ini, dan parameter selanjutnya akan digunakan sebagai parameter fungsi. Solusinya adalah menggunakan ikatan.
fungsi hewan (tipe, kaki) {this.type = type; this.legs = kaki; this.loginfo = function () {console.log (this === mycat); // => true console.log ('the' + this.type + 'memiliki' + this.legs + 'legs'); };} var mycat = hewan baru ('cat', 4); // log "kucing memiliki 4 kaki" setTimeout (mycat.loginfo.bind (mycat), 1000); // setTimeout ?? var John = {firstName: "John", insiden: "smith"} funct func (a, b) {waspada (ini [a] + '' + ini [b])} func.call (John, 'FirstName', 'Name') // "John Smith"Sedangkan untuk berlaku, itu hanya melewati parameter di kuadrat array, dan bagian lainnya sama, seperti berikut:
func.call (John, 'firstName', 'stellame') func.Apply (John, ['firstName', 'Name']))
Mereka juga dapat digunakan dalam warisan kelas di ES5 untuk memanggil konstruktor induk.
function runner (name) {console.log (instance dari kelinci ini); // => true this.name = name; } function rabbit (name, countlegs) {console.log (instance dari kelinci ini); // => true // dipanggil secara tidak langsung, runner konstruktor induk (ini, nama); this.countlegs = countlegs; } var myrabbit = kelinci baru ('kelinci putih', 4); Myrabbit; // {name: 'White Rabbit', Countlegs: 4}5..bind ()
Bandingkan metode .Apply () dan .call (), keduanya segera menjalankan fungsi, sedangkan fungsi .bind () mengembalikan metode baru yang mengikat ini pra-spesifik dan dapat menunda panggilan.
Fungsi metode .bind () adalah membuat fungsi baru. Konteks selama eksekusi adalah parameter pertama yang dilewati oleh .bind (), yang memungkinkan penciptaan fungsi yang memiliki preset ini.
var angka = {array: [3, 5, 10], getNumbers: function () {return this.array; }}; // Buat Bound FunctionVar BoundGetNumbers = numbers.getnumbers.bind (angka); BoundGetNumbers (); // => [3, 5, 10] // Ekstrak metode dari ObjectVar SimpleGetNumbers = number.getNumbers; SimpleGetNumbers (); // => tidak terdefinisi atau melempar kesalahan dalam mode ketatSaat menggunakan .bind (), Anda harus mencatat bahwa .bind () menciptakan rantai konteks abadi dan tidak dapat dimodifikasi. Bahkan jika fungsi pengikatan menggunakan .call () atau .Apply () untuk masuk ke konteks lain yang berbeda, itu tidak akan mengubah konteks koneksi sebelumnya, dan rebinding tidak akan memainkan peran apa pun.
Hanya ketika konstruktor dipanggil, fungsi pengikatan dapat mengubah konteks, tetapi ini bukan pendekatan yang direkomendasikan.
6. Fungsi Panah
Fungsi panah tidak menciptakan konteks eksekusi sendiri, sehingga ini tergantung pada fungsi eksternal yang didefinisikan pada saat definisi.
Fungsi panah tidak dapat diubah setelah mengikat konteks sekali, bahkan jika metode perubahan konteks digunakan:
var angka = [1, 2]; (function () {var get = () => {console.log (this === angka); // => true return this;}; console.log (this === angka); // => true get (); // => [1, 2] // function function. // => [1, 2] // bind get.bind ([0]) ();Ini karena fungsi panah memiliki konteks statis dan tidak akan berubah karena panggilan yang berbeda. Oleh karena itu, jangan gunakan fungsi panah untuk mendefinisikan metode
periode fungsi (jam, menit) {this.hours = jam; this.minutes = menit; } Period.prototype.format = () => {console.log (this === jendela); // => true return this.hours + 'jam dan' + this.minutes + 'menit'; }; var walkperiod = periode baru (2, 30); walkperiod.format (); // => 'jam yang tidak ditentukan dan menit yang tidak ditentukan'merujuk ke
Empat aroma "ini"
Penjelasan lembut tentang kata kunci 'ini' di JavaScript
Javascript Misteri ini (Terjemahan)
Sangat disarankan agar siswa yang tidak memahaminya. Lihat tiga artikel di atas, yang ketiga adalah terjemahan yang kedua. Jika Anda memiliki pertanyaan tentang ini, Anda dipersilakan untuk berdiskusi bersama, berkomunikasi dan mempromosikan pemikiran dan membuat kemajuan bersama.