Tutorial JavaScript: Fungsi pesanan tinggi

Minggu lalu, saya dengan santai menjatuhkan istilah "fungsi pesanan tinggi" ketika bercakap mengenai penghafalan. Walaupun saya berasa selesa untuk membincangkan istilah seperti sekarang, saya tidak selalu tahu maksudnya. Minggu ini kita akan mengkaji fungsi fungsi yang lebih tinggi, menunjukkan beberapa contoh biasa, dan belajar bagaimana membuat sendiri.

Pada intinya, fungsi orde tinggi hanyalah fungsi yang menerima fungsi sebagai argumen atau mengembalikan fungsi. Hal ini dimungkinkan dalam JavaScript berkat fungsi kelas pertama, yang bermaksud bahawa fungsi dalam JavaScript dapat diteruskan seperti pemboleh ubah lain. Walaupun ini terdengar sangat mudah, ia tidak cukup banyak jenis kekuatan yang anda miliki dengan fungsi kelas pertama.

Sekiranya anda menulis JavaScript, anda mungkin telah menggunakan fungsi yang lebih tinggi dan tidak disedari. Sekiranya anda pernah mengganti forgelung dengan kaedah tatasusunan, anda telah menggunakan fungsi susunan lebih tinggi. Sekiranya anda pernah menggunakan hasil panggilan AJAX (tanpa async/ await), anda telah menggunakan fungsi pesanan lebih tinggi (kedua-dua janji dan panggilan balik melibatkan fungsi pesanan lebih tinggi). Sekiranya anda pernah menulis komponen React yang memaparkan senarai item, anda telah menggunakan fungsi pesanan tinggi. Mari lihat contohnya:

item const = ['a', 'b', 'c', 'd', 'e']

// Daripada ini untuk gelung ....

untuk (let i = 0; i <item.length - 1; i ++) {

  console.log (item [i]);

}

// Kita boleh menggunakan forEach, fungsi pesanan tinggi

// (forEach mengambil fungsi sebagai argumen)

item.forEach ((item) => console.log (item));

// Panggilan balik atau janji, jika anda membuat

// permintaan tidak segerak, anda gunakan

// fungsi pesanan tinggi

dapatkan ('// aws.random.cat/meow', (respons) => {

  putImageOnScreen (respons.file);

});

dapatkan ('// random.dog/woof.json').then((response) => {

  putImageOnScreen (respons.file);

});

// Dalam komponen React di bawah, peta digunakan,

// yang merupakan fungsi pesanan tinggi

const myListComponent = (alat peraga) => {

  kembali (

   

          {props.items.map ((item) => {

            kembali (

  • {item}
  • )

          })}

      );

    };

Itu adalah contoh fungsi orde tinggi yang menerima fungsi sebagai argumen, tetapi banyak dari mereka mengembalikan fungsi juga. Sekiranya anda pernah melihat panggilan fungsi yang mempunyai dua set kurungan, itu adalah fungsi yang lebih tinggi. Perkara semacam ini dulu kurang biasa, tetapi jika sama sekali bekerjasama dengan Redux, anda mungkin telah menggunakan connectfungsi tersebut, yang merupakan fungsi pesanan lebih tinggi:

eksport sambung lalai (mapStateToProps, mapDispatchToProps) (MyComponent);

Dalam kes di atas, kami memanggil connectdengan dua argumen dan mengembalikan fungsi, yang kami segera panggil dengan satu argumen. Anda mungkin juga telah melihat (atau menulis) perpustakaan pembalakan sederhana yang menggunakan fungsi sebagai nilai kembali. Dalam contoh di bawah, kami akan membuat logger yang mencatat konteksnya sebelum mesej:

const createLogger = (konteks) => {

  kembali (msg) => {

    console.log (`$ {konteks}: $ {msg}`);

  }

};

const log = createLogger ('myFile');

log ('Mesej yang sangat penting');

// log keluar "myFile: Mesej yang sangat penting"

Contoh di atas mula menggambarkan beberapa kekuatan fungsi pesanan lebih tinggi (lihat juga catatan saya sebelumnya mengenai penghafalan). Perhatikan bahawa createLoggermengambil argumen yang kita rujuk dalam badan fungsi yang kita kembalikan. Fungsi yang dikembalikan itu, yang kita tetapkan pada pemboleh ubah log, masih dapat mengakses contextargumen kerana berada dalam ruang lingkup fungsi yang ditentukan.

Fakta menarik: Rujukan contextdimungkinkan oleh penutupan. Saya tidak akan ditutup di sini kerana mereka layak mendapat jawatan mereka sendiri, tetapi mereka dapat digunakan bersama dengan fungsi pesanan lebih tinggi untuk beberapa kesan yang sangat menarik.

Sebagai contoh, menggunakan penutupan bersama dengan fungsi pesanan yang lebih tinggi dulu adalah satu-satunya cara kita mempunyai pemboleh ubah "peribadi" atau perusak dalam JavaScript:

mari dilindungiObject = (fungsi () {

  biarkan myVar = 0;

  kembali {

    dapatkan: () => myVar,

    kenaikan: () => myVar ++,

  };

}) ();

protectedObject.get (); // mengembalikan 0

protectedObject.increment ();

protectedObject.get (); // mengembalikan 1

myVar = 42; // Alamak! anda baru sahaja membuat pemboleh ubah global

protectedObject.get (); // masih kembali 1

Janganlah kita terbawa-bawa. Fungsi pesanan tinggi tidak memerlukan sesuatu yang mewah seperti penutup. Mereka hanyalah fungsi yang mengambil fungsi lain sebagai argumen atau fungsi mengembalikan. Noktah. Sekiranya anda menginginkan lebih banyak contoh atau bacaan lebih lanjut, lihat bab mengenai fungsi pesanan lebih tinggi dalam "Eloquent JavaScript" oleh Marijn Haverbeke.

Soalan atau komen? Jangan ragu untuk menghubungi Twitter: @freethejazz.