Fungsi JavaScript Bersarang

97

Saya mendapat potongan kode untuk javascript yang tidak saya mengerti:

function dmy(d) {
    function pad2(n) {
        return (n < 10) ? '0' + n : n;
    }

    return pad2(d.getUTCDate()) + '/' +
       pad2(d.getUTCMonth() + 1) + '/' +
       d.getUTCFullYear();
}

function outerFunc(base) {
    var punc = "!";

    //inner function
    function returnString(ext) {
       return base + ext + punc;
    }

    return returnString;
}

Bagaimana suatu fungsi dapat didefinisikan dalam fungsi lain? Bisakah kita memanggil pad2 () dari luar fungsi saya ()?

Tolong beri penerangan padanya. Terima kasih

Thomas
sumber
13
fungsi dapat dibuat di dalam fungsi. Itu sangat valid.
0x499602D2

Jawaban:

140

Fungsi adalah jenis variabel lain dalam JavaScript (tentu saja dengan beberapa nuansa). Membuat fungsi di dalam fungsi lain mengubah ruang lingkup fungsi dengan cara yang sama akan mengubah ruang lingkup variabel. Ini sangat penting untuk digunakan dengan closure guna mengurangi polusi namespace global total.

Fungsi yang ditentukan dalam fungsi lain tidak akan dapat diakses di luar fungsi kecuali jika telah dilampirkan ke objek yang dapat diakses di luar fungsi:

function foo(doBar)
{
  function bar()
  {
    console.log( 'bar' );
  }

  function baz()
  {
    console.log( 'baz' );
  }

  window.baz = baz;
  if ( doBar ) bar();
}

Dalam contoh ini, fungsi baz akan tersedia untuk digunakan setelah foofungsi dijalankan, karena diganti window.baz. Fungsi bilah tidak akan tersedia untuk konteks apa pun selain cakupan yang ada di dalam foofungsi.

sebagai contoh yang berbeda:

function Fizz(qux)
{
  this.buzz = function(){
    console.log( qux );
  };
}

The FizzFungsi dirancang sebagai konstruktor sehingga, ketika dijalankan, akan menetapkan sebuah buzzfungsi untuk objek yang baru dibuat.

zzzzBov
sumber
Apa itu window.baz = baz? Mengapa jalur m? Ke baz ini tersedia?
Ziyang Zhang
@ZiyangZhang, di paragraf setelah blok kode itu ada penjelasannya, apakah ada bagian tertentu yang tidak jelas?
zzzzBov
35

Ini disebut penutupan .

Pada dasarnya, fungsi yang ditentukan dalam fungsi lain hanya dapat diakses di dalam fungsi ini. Tetapi dapat dilewati sebagai hasil dan kemudian hasil ini dapat dipanggil.

Ini adalah fitur yang sangat kuat. Anda dapat melihat penjelasan lebih lanjut di sini:

javascript_closures_for_dummies.html mirror di Archive.org

Tadeck
sumber
13
function x() {}

setara (atau sangat mirip) dengan

var x = function() {}

kecuali saya salah.

Jadi tidak ada hal lucu yang terjadi.

Andreas
sumber
8
Sintaks pertama akan dipindahkan ke awal dokumen. sehingga dimungkinkan untuk memanggil fungsi 'x' sebelum funtion diinisialisasi.
Tom
10
Sintaks pertama juga akan memberi Anda jejak tumpukan yang jauh lebih baik dengan fungsi bernama, yang kedua akan membuat Anda pusing
TheZ
@TheZ Saya pikir Chrome baru-baru ini menambahkan inferensi nama fungsi ke debugging sehingga Anda tidak mendapatkan sakit kepala yang sama seperti sebelumnya dalam kasus umum.
jinglesthula
@jinglesthula Ya! Chrome menambahkan inferensi nama ini beberapa waktu lalu dan sangat dihargai :)
TheZ
10

Instansiasi fungsi diperbolehkan di dalam dan di luar fungsi. Di dalam fungsi tersebut, seperti halnya variabel, fungsi yang disarangkan bersifat lokal dan oleh karena itu tidak dapat diperoleh dari lingkup luar.

function foo() {
    function bar() {
        return 1;
    }
    return bar();
}

foomemanipulasi bardalam dirinya sendiri. bartidak dapat disentuh dari lingkup luar kecuali ditentukan di lingkup luar.

Jadi ini tidak akan berhasil:

function foo() {
    function bar() {
        return 1;
    }
}

bar(); // throws error: bar is not defined
0x499602D2
sumber
4

Saat Anda mendeklarasikan suatu fungsi dalam suatu fungsi, fungsi dalam hanya tersedia dalam cakupan di mana fungsi tersebut dideklarasikan, atau dalam kasus Anda, pad2hanya dapat dipanggil didmy cakupan tersebut.

Semua variabel yang ada dmyterlihat di pad2, tetapi tidak terjadi sebaliknya: D

pedrochave
sumber
2

Sangat normal dalam Javascript (dan banyak bahasa) untuk memiliki fungsi di dalam fungsi.

Luangkan waktu untuk mempelajari bahasanya, jangan menggunakannya atas dasar bahwa itu mirip dengan yang sudah Anda ketahui. Saya sarankan menonton seri presentasi YUI Douglas Crockford tentang Javascript, dengan fokus khusus pada Act III: Function the Ultimate (tautan ke unduhan video, slide, dan transkrip)

Joaquim Rendeiro
sumber
0

function foo() {
  function bar() {
    return 1;
  }
}
bar();

Akan menimbulkan kesalahan. Karena bardidefinisikan di dalam foo, barhanya akan dapat diakses di dalam foo.
Untuk menggunakan barAnda perlu menjalankannya di dalam foo.

function foo() {
  function bar() {
    return 1;
  }
  bar();
}

Justin Liu
sumber