Bagaimana Anda menggunakan variabel di dalam fungsi di javascript?

Untuk mengakses variabel di luar fungsi dalam JavaScript, buat variabel Anda dapat diakses dari luar fungsi. Pertama, nyatakan di luar fungsi, lalu gunakan di dalam fungsi

function one(){
   var a;
   function two(){
       a = 10;
       return a;
   }
   return two();
}

Anda tidak dapat mengakses variabel yang dideklarasikan di dalam fungsi dari luar fungsi. Variabel milik ruang lingkup fungsi saja, bukan ruang lingkup global

Akses variabel di luar fungsi dalam JavaScript

Contoh sederhana variabel akses kode di luar ruang lingkup fungsi

<!DOCTYPE html>
<html>
<body>
  <script>    
    function one(){
     var a;

     function two(){
      a = 100;
      console.log("Inner function")
      return a;
    }
    return two();
  }
   var res = one();
  console.log(res)
</script>  

</body>
</html>
_

Keluaran

Bagaimana Anda menggunakan variabel di dalam fungsi di javascript?

Cara lain adalah Tidak menempatkan "var", "biarkan" atau "const" akan membuat variabel Publik Dan dapat digunakan di luar fungsi

function Play(){
  	Video = 12 // Seconds
	var Length = 15
}
console.log(Video) // Prints 12
console.log(Length) // "Lenght" is undefined

mengubah variabel di luar fungsi js

var global = "Global Variable"; //Define global variable outside of function

function setGlobal(){
       global = "Hello World!";
};
setGlobal();
console.log(global); //This will print out "Hello World"

Berikan komentar jika Anda memiliki keraguan atau saran tentang topik variabel Js ini

Catatan. Semua kode Contoh JS diuji di browser Firefox dan browser Chrome

OS. Windows 10

Kode. Versi HTML5

Bagaimana Anda menggunakan variabel di dalam fungsi di javascript?

Rohit

Gelar dalam Ilmu Komputer dan Insinyur. Pengembang Aplikasi dan memiliki banyak pengalaman bahasa Pemrograman. Antusias terhadap teknologi & suka belajar teknis

Namun, jika Anda membuat variabel di dalam lingkup fungsi dengan nama yang sama dengan variabelglobal, Anda kehilangan akses ke nilai globalVariable di dalam lingkup fungsi

Jika Anda membaca kode di atas berdasarkan urutan baris mana yang dieksekusi, inilah yang menurut Anda akan terjadi

  • buat globalVariable dan berikan nilai
  • Panggil beberapaFungsi
  • nilai log globalVariable ke konsol. Anda akan mengharapkan ini untuk mencatat I am a globalvariable
  • buat variabel lokal baru dengan nama yang sama dengan globalVariable. globalVariable dan beri nilai
  • Catat variabel lokal baru ini. Anda akan mengharapkan I am a local variable as the same name as globalVariable untuk dicetak

Namun, Anda benar-benar mendapatkan kesalahan. Javascript akan memberitahu Anda bahwa globalVariable tidak didefinisikan ReferenceError:globalVariable is not defined

Penjelasan

Ini karena terlepas dari di mana Anda mendefinisikan variabel Anda, itu akan mengangkat variabel ke atas cakupan terlampir. Yang berarti, jika suatu variabel didefinisikan dalam suatu ruang lingkup, javascript memindahkannya sepenuhnya ke bagian atas ruang lingkup. Ini adalah alasan yang sama Anda dapat memanggil fungsi dalam javascript di baris 1 meskipun fungsi tersebut tidak ditentukan hingga baris 2

Akibatnya dalam contoh kedua, Anda kehilangan akses ke globalVariable yang ditentukan di luar cakupan fungsi, karena telah diangkat ke atas cakupan (alias di dalam fungsi)

JavaScript adalah bahasa yang sangat berorientasi pada fungsi. Ini memberi kita banyak kebebasan. Suatu fungsi dapat dibuat kapan saja, diteruskan sebagai argumen ke fungsi lain, dan kemudian dipanggil dari tempat kode yang sama sekali berbeda nanti

Kita sudah tahu bahwa suatu fungsi dapat mengakses variabel di luarnya (variabel "luar")

Tetapi apa yang terjadi jika variabel luar berubah sejak suatu fungsi dibuat?

Dan bagaimana jika suatu fungsi diteruskan sebagai argumen dan dipanggil dari tempat kode lain, apakah ia akan mendapatkan akses ke variabel luar di tempat baru?

Mari perluas pengetahuan kita untuk memahami skenario ini dan yang lebih kompleks

Kami akan berbicara tentang

{
  // show message
  let message = "Hello";
  alert(message);
}

{
  // show another message
  let message = "Goodbye";
  alert(message);
}
3 variabel di sini

Dalam JavaScript, ada 3 cara untuk mendeklarasikan variabel.

{
  // show message
  let message = "Hello";
  alert(message);
}

{
  // show another message
  let message = "Goodbye";
  alert(message);
}
_4,
{
  // show message
  let message = "Hello";
  alert(message);
}

{
  // show another message
  let message = "Goodbye";
  alert(message);
}
5 (yang modern), dan
{
  // show message
  let message = "Hello";
  alert(message);
}

{
  // show another message
  let message = "Goodbye";
  alert(message);
}
6 (sisa masa lalu)

  • Dalam artikel ini kita akan menggunakan
    {
      // show message
      let message = "Hello";
      alert(message);
    }
    
    {
      // show another message
      let message = "Goodbye";
      alert(message);
    }
    _4 variabel sebagai contoh
  • Variabel, dideklarasikan dengan
    {
      // show message
      let message = "Hello";
      alert(message);
    }
    
    {
      // show another message
      let message = "Goodbye";
      alert(message);
    }
    _5, berperilaku sama, jadi artikel ini juga tentang
    {
      // show message
      let message = "Hello";
      alert(message);
    }
    
    {
      // show another message
      let message = "Goodbye";
      alert(message);
    }
    5
  • {
      // show message
      let message = "Hello";
      alert(message);
    }
    
    {
      // show another message
      let message = "Goodbye";
      alert(message);
    }
    _6 lama memiliki beberapa perbedaan penting, mereka akan dibahas dalam artikel "var" lama

Jika sebuah variabel dideklarasikan di dalam blok kode

// show message
let message = "Hello";
alert(message);

// show another message
let message = "Goodbye"; // Error: variable already declared
alert(message);
1, itu hanya terlihat di dalam blok itu

Sebagai contoh

{
  // do some job with local variables that should not be seen outside

  let message = "Hello"; // only visible in this block

  alert(message); // Hello
}

alert(message); // Error: message is not defined

Kita dapat menggunakan ini untuk mengisolasi sepotong kode yang melakukan tugasnya sendiri, dengan variabel yang hanya menjadi miliknya

{
  // show message
  let message = "Hello";
  alert(message);
}

{
  // show another message
  let message = "Goodbye";
  alert(message);
}
_

Akan ada kesalahan tanpa blok

Harap dicatat, tanpa blok terpisah akan ada kesalahan, jika kita menggunakan

{
  // show message
  let message = "Hello";
  alert(message);
}

{
  // show another message
  let message = "Goodbye";
  alert(message);
}
4 dengan nama variabel yang ada

// show message
let message = "Hello";
alert(message);

// show another message
let message = "Goodbye"; // Error: variable already declared
alert(message);

Untuk

// show message
let message = "Hello";
alert(message);

// show another message
let message = "Goodbye"; // Error: variable already declared
alert(message);
_3,
// show message
let message = "Hello";
alert(message);

// show another message
let message = "Goodbye"; // Error: variable already declared
alert(message);
4,
// show message
let message = "Hello";
alert(message);

// show another message
let message = "Goodbye"; // Error: variable already declared
alert(message);
5 dan seterusnya, variabel yang dideklarasikan dalam
// show message
let message = "Hello";
alert(message);

// show another message
let message = "Goodbye"; // Error: variable already declared
alert(message);
1 juga hanya terlihat di dalam

if (true) {
  let phrase = "Hello!";

  alert(phrase); // Hello!
}

alert(phrase); // Error, no such variable!

Di sini, setelah

// show message
let message = "Hello";
alert(message);

// show another message
let message = "Goodbye"; // Error: variable already declared
alert(message);
_3 selesai,
// show message
let message = "Hello";
alert(message);

// show another message
let message = "Goodbye"; // Error: variable already declared
alert(message);
8 di bawah tidak akan melihat
// show message
let message = "Hello";
alert(message);

// show another message
let message = "Goodbye"; // Error: variable already declared
alert(message);
9, maka kesalahan

Itu bagus, karena memungkinkan kita membuat variabel blok-lokal, khusus untuk cabang

// show message
let message = "Hello";
alert(message);

// show another message
let message = "Goodbye"; // Error: variable already declared
alert(message);
3

Hal serupa berlaku untuk

// show message
let message = "Hello";
alert(message);

// show another message
let message = "Goodbye"; // Error: variable already declared
alert(message);
_4 dan
// show message
let message = "Hello";
alert(message);

// show another message
let message = "Goodbye"; // Error: variable already declared
alert(message);
5 loop

for (let i = 0; i < 3; i++) {
  // the variable i is only visible inside this for
  alert(i); // 0, then 1, then 2
}

alert(i); // Error, no such variable

Secara visual,

if (true) {
  let phrase = "Hello!";

  alert(phrase); // Hello!
}

alert(phrase); // Error, no such variable!
_3 berada di luar
// show message
let message = "Hello";
alert(message);

// show another message
let message = "Goodbye"; // Error: variable already declared
alert(message);
1. Tapi konstruksi
// show message
let message = "Hello";
alert(message);

// show another message
let message = "Goodbye"; // Error: variable already declared
alert(message);
_4 spesial di sini. variabel, yang dideklarasikan di dalamnya, dianggap sebagai bagian dari blok

Suatu fungsi disebut "bersarang" ketika dibuat di dalam fungsi lain

Sangat mudah untuk melakukan ini dengan JavaScript

Kita dapat menggunakannya untuk mengatur kode kita, seperti ini

function sayHiBye(firstName, lastName) {

  // helper nested function to use below
  function getFullName() {
    return firstName + " " + lastName;
  }

  alert( "Hello, " + getFullName() );
  alert( "Bye, " + getFullName() );

}

Di sini fungsi bersarang

if (true) {
  let phrase = "Hello!";

  alert(phrase); // Hello!
}

alert(phrase); // Error, no such variable!
_6 dibuat untuk kenyamanan. Itu dapat mengakses variabel luar dan dapat mengembalikan nama lengkap. Fungsi bersarang cukup umum dalam JavaScript

Yang jauh lebih menarik, fungsi bersarang dapat dikembalikan. baik sebagai properti objek baru atau sebagai hasil dengan sendirinya. Ini kemudian dapat digunakan di tempat lain. Di mana pun, ia masih memiliki akses ke variabel luar yang sama

Di bawah,

if (true) {
  let phrase = "Hello!";

  alert(phrase); // Hello!
}

alert(phrase); // Error, no such variable!
_7 membuat fungsi "penghitung" yang mengembalikan angka berikutnya pada setiap pemanggilan

function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();

alert( counter() ); // 0
alert( counter() ); // 1
alert( counter() ); // 2

Meskipun sederhana, varian kode yang sedikit dimodifikasi memiliki kegunaan praktis, misalnya, sebagai penghasil angka acak untuk menghasilkan nilai acak untuk pengujian otomatis

Bagaimana cara kerjanya?

Memahami hal-hal seperti itu bagus untuk keseluruhan pengetahuan JavaScript dan bermanfaat untuk skenario yang lebih kompleks. Jadi mari kita sedikit lebih dalam

Di sini jadilah naga

Penjelasan teknis mendalam ada di depan

Sejauh saya ingin menghindari detail bahasa tingkat rendah, pemahaman apa pun tanpanya akan kurang dan tidak lengkap, jadi bersiaplah

Untuk kejelasan, penjelasannya dibagi menjadi beberapa langkah

Dalam JavaScript, setiap fungsi yang berjalan, blok kode

// show message
let message = "Hello";
alert(message);

// show another message
let message = "Goodbye"; // Error: variable already declared
alert(message);
1, dan skrip secara keseluruhan memiliki objek terkait internal (tersembunyi) yang dikenal sebagai Lingkungan Lexical

Objek Lexical Environment terdiri dari dua bagian

  1. Rekaman Lingkungan – objek yang menyimpan semua variabel lokal sebagai propertinya (dan beberapa informasi lain seperti nilai
    if (true) {
      let phrase = "Hello!";
    
      alert(phrase); // Hello!
    }
    
    alert(phrase); // Error, no such variable!
    9)
  2. Referensi ke lingkungan leksikal luar, yang terkait dengan kode luar

"Variabel" hanyalah properti dari objek internal khusus,

for (let i = 0; i < 3; i++) {
  // the variable i is only visible inside this for
  alert(i); // 0, then 1, then 2
}

alert(i); // Error, no such variable
0. "Untuk mendapatkan atau mengubah variabel" berarti "mendapatkan atau mengubah properti dari objek itu"

Dalam kode sederhana tanpa fungsi ini, hanya ada satu Lingkungan Lexical

Inilah yang disebut Lingkungan Leksikal global, yang terkait dengan keseluruhan naskah

Pada gambar di atas, persegi panjang berarti Rekam Lingkungan (penyimpanan variabel) dan tanda panah berarti referensi luar. Lingkungan Leksikal global tidak memiliki referensi luar, itu sebabnya panah menunjuk ke

for (let i = 0; i < 3; i++) {
  // the variable i is only visible inside this for
  alert(i); // 0, then 1, then 2
}

alert(i); // Error, no such variable
1

Saat kode mulai dijalankan dan berlanjut, Lingkungan Lexical berubah

Ini kode yang sedikit lebih panjang

Persegi panjang di sisi kanan menunjukkan bagaimana Lingkungan Leksikal global berubah selama eksekusi

  1. Saat skrip dimulai, Lingkungan Lexical telah diisi sebelumnya dengan semua variabel yang dideklarasikan
    • Awalnya, mereka berada dalam status "Tidak diinisialisasi". Itu adalah keadaan internal khusus, artinya mesin tahu tentang variabel, tetapi tidak dapat direferensikan sampai dideklarasikan dengan
      {
        // show message
        let message = "Hello";
        alert(message);
      }
      
      {
        // show another message
        let message = "Goodbye";
        alert(message);
      }
      4. Ini hampir sama seperti jika variabelnya tidak ada
  2. Kemudian
    for (let i = 0; i < 3; i++) {
      // the variable i is only visible inside this for
      alert(i); // 0, then 1, then 2
    }
    
    alert(i); // Error, no such variable
    _3 definisi muncul. Belum ada penugasan, jadi nilainya adalah
    for (let i = 0; i < 3; i++) {
      // the variable i is only visible inside this for
      alert(i); // 0, then 1, then 2
    }
    
    alert(i); // Error, no such variable
    4. Kita dapat menggunakan variabel dari titik ini ke depan
  3. // show message
    let message = "Hello";
    alert(message);
    
    // show another message
    let message = "Goodbye"; // Error: variable already declared
    alert(message);
    9 diberi nilai
  4. // show message
    let message = "Hello";
    alert(message);
    
    // show another message
    let message = "Goodbye"; // Error: variable already declared
    alert(message);
    9 mengubah nilainya

Semuanya terlihat sederhana untuk saat ini, bukan?

  • Variabel adalah properti dari objek internal khusus, terkait dengan blok/fungsi/skrip yang sedang dieksekusi
  • Bekerja dengan variabel sebenarnya bekerja dengan properti objek itu

Leksikal Lingkungan adalah objek spesifikasi

"Lexical Environment" adalah objek spesifikasi. itu hanya ada "secara teoritis" untuk menggambarkan cara kerja sesuatu. Kami tidak bisa mendapatkan objek ini dalam kode kami dan memanipulasinya secara langsung

Mesin JavaScript juga dapat mengoptimalkannya, membuang variabel yang tidak digunakan untuk menghemat memori dan melakukan trik internal lainnya, selama perilaku yang terlihat tetap seperti yang dijelaskan

Fungsi juga merupakan nilai, seperti variabel

Perbedaannya adalah Deklarasi Fungsi langsung diinisialisasi sepenuhnya

Ketika Lingkungan Leksikal dibuat, Deklarasi Fungsi segera menjadi fungsi siap pakai (tidak seperti

{
  // show message
  let message = "Hello";
  alert(message);
}

{
  // show another message
  let message = "Goodbye";
  alert(message);
}
4, yang tidak dapat digunakan sampai deklarasi)

Itu sebabnya kita bisa menggunakan fungsi, dideklarasikan sebagai Deklarasi Fungsi, bahkan sebelum deklarasi itu sendiri

Misalnya, inilah keadaan awal Lingkungan Lexical global saat kita menambahkan sebuah fungsi

Secara alami, perilaku ini hanya berlaku untuk Deklarasi Fungsi, bukan Ekspresi Fungsi di mana kita menetapkan fungsi ke variabel, seperti

for (let i = 0; i < 3; i++) {
  // the variable i is only visible inside this for
  alert(i); // 0, then 1, then 2
}

alert(i); // Error, no such variable
8

Ketika suatu fungsi berjalan, pada awal panggilan, Lingkungan Lexical baru dibuat secara otomatis untuk menyimpan variabel lokal dan parameter panggilan

Misalnya, untuk

for (let i = 0; i < 3; i++) {
  // the variable i is only visible inside this for
  alert(i); // 0, then 1, then 2
}

alert(i); // Error, no such variable
_9, tampilannya seperti ini (eksekusinya ada di baris, diberi tanda panah)

Selama pemanggilan fungsi, kami memiliki dua Lingkungan Lexical. bagian dalam (untuk pemanggilan fungsi) dan bagian luar (global)

  • Lingkungan Leksikal bagian dalam sesuai dengan eksekusi
    function sayHiBye(firstName, lastName) {
    
      // helper nested function to use below
      function getFullName() {
        return firstName + " " + lastName;
      }
    
      alert( "Hello, " + getFullName() );
      alert( "Bye, " + getFullName() );
    
    }
    0 saat ini. Ia memiliki satu properti.
    function sayHiBye(firstName, lastName) {
    
      // helper nested function to use below
      function getFullName() {
        return firstName + " " + lastName;
      }
    
      alert( "Hello, " + getFullName() );
      alert( "Bye, " + getFullName() );
    
    }
    _1, argumen fungsi. Kami memanggil
    for (let i = 0; i < 3; i++) {
      // the variable i is only visible inside this for
      alert(i); // 0, then 1, then 2
    }
    
    alert(i); // Error, no such variable
    _9, jadi nilai
    function sayHiBye(firstName, lastName) {
    
      // helper nested function to use below
      function getFullName() {
        return firstName + " " + lastName;
      }
    
      alert( "Hello, " + getFullName() );
      alert( "Bye, " + getFullName() );
    
    }
    1 adalah
    function sayHiBye(firstName, lastName) {
    
      // helper nested function to use below
      function getFullName() {
        return firstName + " " + lastName;
      }
    
      alert( "Hello, " + getFullName() );
      alert( "Bye, " + getFullName() );
    
    }
    4
  • Lingkungan Leksikal luar adalah Lingkungan Leksikal global. Ia memiliki variabel
    // show message
    let message = "Hello";
    alert(message);
    
    // show another message
    let message = "Goodbye"; // Error: variable already declared
    alert(message);
    _9 dan fungsi itu sendiri

Lingkungan Leksikal batin memiliki referensi ke

function sayHiBye(firstName, lastName) {

  // helper nested function to use below
  function getFullName() {
    return firstName + " " + lastName;
  }

  alert( "Hello, " + getFullName() );
  alert( "Bye, " + getFullName() );

}
6

Ketika kode ingin mengakses variabel – Lingkungan Lexical bagian dalam dicari terlebih dahulu, lalu yang terluar, lalu yang lebih terluar dan seterusnya hingga yang global

Jika variabel tidak ditemukan di mana pun, itu adalah kesalahan dalam mode ketat (tanpa

function sayHiBye(firstName, lastName) {

  // helper nested function to use below
  function getFullName() {
    return firstName + " " + lastName;
  }

  alert( "Hello, " + getFullName() );
  alert( "Bye, " + getFullName() );

}
7, penugasan ke variabel yang tidak ada membuat variabel global baru, untuk kompatibilitas dengan kode lama)

Dalam contoh ini hasil pencarian sebagai berikut

  • Untuk variabel
    function sayHiBye(firstName, lastName) {
    
      // helper nested function to use below
      function getFullName() {
        return firstName + " " + lastName;
      }
    
      alert( "Hello, " + getFullName() );
      alert( "Bye, " + getFullName() );
    
    }
    1,
    // show message
    let message = "Hello";
    alert(message);
    
    // show another message
    let message = "Goodbye"; // Error: variable already declared
    alert(message);
    8 di dalam
    function sayHiBye(firstName, lastName) {
    
      // helper nested function to use below
      function getFullName() {
        return firstName + " " + lastName;
      }
    
      alert( "Hello, " + getFullName() );
      alert( "Bye, " + getFullName() );
    
    }
    0 menemukannya langsung di Lingkungan Leksikal bagian dalam
  • Ketika ingin mengakses
    // show message
    let message = "Hello";
    alert(message);
    
    // show another message
    let message = "Goodbye"; // Error: variable already declared
    alert(message);
    _9, maka tidak ada
    // show message
    let message = "Hello";
    alert(message);
    
    // show another message
    let message = "Goodbye"; // Error: variable already declared
    alert(message);
    9 secara lokal, sehingga mengikuti referensi ke Lingkungan Lexical luar dan menemukannya di sana

Mari kembali ke contoh ________21______7

function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();

Di awal setiap panggilan

function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();

alert( counter() ); // 0
alert( counter() ); // 1
alert( counter() ); // 2
_4, objek Lexical Environment baru dibuat, untuk menyimpan variabel untuk proses
if (true) {
  let phrase = "Hello!";

  alert(phrase); // Hello!
}

alert(phrase); // Error, no such variable!
7 ini

Jadi kami memiliki dua Lingkungan Leksikal bersarang, seperti pada contoh di atas

Apa yang berbeda adalah, selama eksekusi

function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();

alert( counter() ); // 0
alert( counter() ); // 1
alert( counter() ); // 2
4, fungsi bersarang kecil dibuat hanya dari satu baris.
function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();

alert( counter() ); // 0
alert( counter() ); // 1
alert( counter() ); // 2
_7. Kami belum menjalankannya, hanya membuat

Semua fungsi mengingat Lingkungan Leksikal tempat mereka dibuat. Secara teknis, tidak ada keajaiban di sini. semua fungsi memiliki properti tersembunyi bernama

function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();

alert( counter() ); // 0
alert( counter() ); // 1
alert( counter() ); // 2
_8, yang menyimpan referensi ke Lingkungan Leksikal tempat fungsi dibuat

Jadi,

function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();

alert( counter() ); // 0
alert( counter() ); // 1
alert( counter() ); // 2
_9 memiliki referensi ke
function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();
0 Leksikal Lingkungan. Begitulah fungsi mengingat di mana ia dibuat, di mana pun ia dipanggil. Referensi
function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();

alert( counter() ); // 0
alert( counter() ); // 1
alert( counter() ); // 2
_8 disetel sekali dan selamanya pada waktu pembuatan fungsi

Kemudian, ketika

function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();
2 dipanggil, Lingkungan Leksikal baru dibuat untuk panggilan tersebut, dan referensi Lingkungan Leksikal luarnya diambil dari
function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();

alert( counter() ); // 0
alert( counter() ); // 1
alert( counter() ); // 2
9

Sekarang ketika kode di dalam

function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();
_2 mencari variabel
function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();
5, pertama-tama ia mencari Lingkungan Lexical-nya sendiri (kosong, karena tidak ada variabel lokal di sana), kemudian Lingkungan Lexical dari panggilan
function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();

alert( counter() ); // 0
alert( counter() ); // 1
alert( counter() ); // 2
4 luar, di mana ia menemukan dan mengubahnya

Variabel diperbarui di Lingkungan Lexical tempatnya berada

Inilah keadaan setelah eksekusi

Jika kita memanggil

function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();
2 beberapa kali, variabel
function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();
5 akan dinaikkan menjadi
function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();
9,
function f() {
  let value = 123;

  return function() {
    alert(value);
  }
}

let g = f(); // g.[[Environment]] stores a reference to the Lexical Environment
// of the corresponding f() call
0 dan seterusnya, di tempat yang sama

Penutupan

Ada istilah pemrograman umum "penutupan", yang umumnya harus diketahui oleh pengembang

Penutupan adalah fungsi yang mengingat variabel luarnya dan dapat mengaksesnya. Dalam beberapa bahasa, itu tidak mungkin, atau sebuah fungsi harus ditulis dengan cara khusus untuk mewujudkannya. Tapi seperti yang dijelaskan di atas, dalam JavaScript, semua fungsi secara alami adalah penutupan (hanya ada satu pengecualian, untuk dicakup dalam sintaks "Fungsi baru")

Itu adalah. mereka secara otomatis mengingat di mana mereka dibuat menggunakan properti

function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();

alert( counter() ); // 0
alert( counter() ); // 1
alert( counter() ); // 2
8 tersembunyi, dan kemudian kode mereka dapat mengakses variabel luar

Ketika dalam sebuah wawancara, pengembang frontend mendapat pertanyaan tentang "apa itu penutupan?", Jawaban yang valid adalah definisi penutupan dan penjelasan bahwa semua fungsi dalam JavaScript adalah penutupan, dan mungkin beberapa kata lagi tentang detail teknis. properti

function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();

alert( counter() ); // 0
alert( counter() ); // 1
alert( counter() ); // 2
_8 dan bagaimana Leksikal Lingkungan bekerja

Biasanya, Lingkungan Lexical dihapus dari memori dengan semua variabel setelah pemanggilan fungsi selesai. Itu karena tidak ada referensi untuk itu. Seperti objek JavaScript apa pun, itu hanya disimpan dalam memori saat dapat dijangkau

Namun, jika ada fungsi bersarang yang masih dapat dijangkau setelah fungsi berakhir, maka fungsi tersebut memiliki properti

function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();

alert( counter() ); // 0
alert( counter() ); // 1
alert( counter() ); // 2
8 yang mereferensikan lingkungan leksikal

Dalam hal itu Lingkungan Leksikal masih dapat dijangkau bahkan setelah fungsi selesai, sehingga tetap hidup

Sebagai contoh

function f() {
  let value = 123;

  return function() {
    alert(value);
  }
}

let g = f(); // g.[[Environment]] stores a reference to the Lexical Environment
// of the corresponding f() call

Perhatikan bahwa jika

function f() {
  let value = 123;

  return function() {
    alert(value);
  }
}

let g = f(); // g.[[Environment]] stores a reference to the Lexical Environment
// of the corresponding f() call
4 dipanggil berkali-kali, dan fungsi yang dihasilkan disimpan, maka semua objek Leksikal Lingkungan yang sesuai juga akan disimpan di memori. Dalam kode di bawah ini, ketiganya

function f() {
  let value = Math.random();

  return function() { alert(value); };
}

// 3 functions in array, every one of them links to Lexical Environment
// from the corresponding f() run
let arr = [f(), f(), f()];

Objek Lingkungan Leksikal mati ketika menjadi tidak terjangkau (sama seperti objek lainnya). Dengan kata lain, itu hanya ada jika setidaknya ada satu fungsi bersarang yang mereferensikannya

Dalam kode di bawah ini, setelah fungsi bersarang dihapus, Lingkungan Lexical terlampir (dan karenanya

function f() {
  let value = 123;

  return function() {
    alert(value);
  }
}

let g = f(); // g.[[Environment]] stores a reference to the Lexical Environment
// of the corresponding f() call
5) dibersihkan dari memori

{
  // show message
  let message = "Hello";
  alert(message);
}

{
  // show another message
  let message = "Goodbye";
  alert(message);
}
_0

Seperti yang telah kita lihat, dalam teori saat sebuah fungsi aktif, semua variabel luar juga dipertahankan

Namun dalam praktiknya, mesin JavaScript mencoba mengoptimalkannya. Mereka menganalisis penggunaan variabel dan jika jelas dari kode bahwa variabel luar tidak digunakan – itu akan dihapus

Efek samping yang penting di V8 (Chrome, Edge, Opera) adalah bahwa variabel tersebut tidak akan tersedia dalam proses debug

Coba jalankan contoh di bawah ini di Chrome dengan Alat Pengembang terbuka

Saat dijeda, di konsol ketik

function f() {
  let value = 123;

  return function() {
    alert(value);
  }
}

let g = f(); // g.[[Environment]] stores a reference to the Lexical Environment
// of the corresponding f() call
6

{
  // show message
  let message = "Hello";
  alert(message);
}

{
  // show another message
  let message = "Goodbye";
  alert(message);
}
_1

Seperti yang Anda lihat – tidak ada variabel seperti itu. Secara teori, itu harus dapat diakses, tetapi mesin mengoptimalkannya

Itu dapat menyebabkan masalah debug yang lucu (jika tidak memakan waktu). Salah satunya – kita bisa melihat variabel luar dengan nama yang sama, bukan yang diharapkan

{
  // show message
  let message = "Hello";
  alert(message);
}

{
  // show another message
  let message = "Goodbye";
  alert(message);
}
_2

Fitur V8 ini baik untuk diketahui. Jika Anda melakukan debug dengan Chrome/Edge/Opera, cepat atau lambat Anda akan menemukannya

Itu bukan bug di debugger, melainkan fitur khusus V8. Mungkin suatu saat akan diubah. Anda selalu dapat memeriksanya dengan menjalankan contoh di halaman ini

Bagaimana cara memanggil variabel dalam suatu fungsi di JavaScript?

Setelah mendeklarasikan variabel atau fungsi dengan kata kunci var, Anda dapat memanggilnya kapan saja dengan memanggil namanya .

Bisakah Anda memasukkan variabel ke dalam suatu fungsi?

Biasanya, saat Anda membuat variabel di dalam suatu fungsi, variabel itu bersifat lokal, dan hanya dapat digunakan di dalam fungsi itu . Untuk membuat variabel global di dalam suatu fungsi, Anda dapat menggunakan kata kunci global.

Bisakah Anda membuat variabel di dalam fungsi di JavaScript?

JavaScript memiliki ruang lingkup fungsi. Setiap fungsi menciptakan ruang lingkup baru. Variabel yang didefinisikan di dalam fungsi tidak dapat diakses (terlihat) dari luar fungsi . Variabel yang dideklarasikan dengan var , let dan const sangat mirip ketika dideklarasikan di dalam suatu fungsi.

Bagaimana cara mengakses variabel di luar fungsi dalam JavaScript?

Variabel lokal tidak dapat diakses di luar deklarasi fungsi. Variabel global dan variabel lokal dapat memiliki nama yang sama tanpa mempengaruhi satu sama lain. JavaScript tidak mengizinkan cakupan level blok di dalam tanda kurung {}