Apakah penutupan? Mari kita bincangkan tentang penutupan dalam JavaScript dan lihat apakah fungsinya?

青灯夜游
Lepaskan: 2022-07-08 11:14:54
ke hadapan
1667 orang telah melayarinya

Apakah itu penutupan? Lihat apa yang dilakukan oleh penutupan? Artikel berikut akan membincangkan tentang penutupan dalam JavaScript. Ia mempunyai nilai rujukan tertentu Rakan-rakan yang memerlukan boleh merujuk kepadanya.

Apakah penutupan? Mari kita bincangkan tentang penutupan dalam JavaScript dan lihat apakah fungsinya?

Dalam proses pembelajaran front-end, kita pasti akan menghadapi banyak masalah, jadi hari ini kita akan bercakap tentang dua masalah dari perspektif seorang pemula:

Apakah itu penutupan?

Apakah fungsi penutupan?

Malah, penutupan ada di mana-mana apabila kita belajar javascript, anda hanya perlu mengenali dan menerimanya. Penutupan bukanlah alat yang memerlukan pembelajaran sintaks atau corak baharu untuk digunakan. Penutupan adalah akibat semula jadi daripada menulis kod berdasarkan skop leksikal. Kami jarang perlu sengaja membuat penutupan semasa menulis kod.

Saya percaya ramai kawan-kawan yang sudah merungut dalam hati ketika ini, apakah skop leksikal ini, jangan panik, dengar saya secara perlahan-lahan pentas. Dalam erti kata lain, skop leksikal ditentukan oleh tempat anda meletakkan pembolehubah dan skop peringkat blok apabila anda menulis kod, jadi skop kekal tidak berubah apabila penganalisis leksikal memproses kod (kebanyakan masa) . ——"JavaScript JavaScript Anda Tidak Tahu"

Mari kita ambil contoh dahulu

function test(){
   var arr = []
   for(var i=0;i<10;i++){
       arr[i]=function(){
           console.log(i);
       }
   }
   return arr
}

var myArr = test()
// myArr[0]()
// myArr[1]()
// ...

for(var j = 0; j < 10; j++){ 
   myArr[j]()
}
//为了避免繁琐此处使用了第二个循环来调用test函数里第一个循环里函数的打印出十个结果
Salin selepas log masuk

Mari kita analisa kod ini dahulu: Apabila kod ini dilaksanakan, mengikut analisis akal, sepuluh nombor dari 0 hingga 9 harus dicetak dalam urutan tetapi gelung for tidak mengambil masa untuk dijalankan (boleh diabaikan dalam mikrosaat Apabila ujian fungsi kembali arr, arr[). ] Di dalamnya terdapat 10 function(){console.log(i);}. Pada masa ini, fungsi dalam tatasusunan tidak dilaksanakan Apabila var myArr = test() memanggil fungsi ujian, sejak masa pelaksanaan gelung untuk diabaikan, ini Pada masa ini, saya sudah 10, jadi 10 10s dicetak.

Saya percaya seseorang akan bertanya pada masa ini, apa kaitannya dengan penutupan yang kita bicarakan Jadi bagaimana jika kita mengubah sedikit kod ini dan mengubahnya menjadi akumulator? ?

Saya percaya akan ada peluang besar pada masa ini siapa yang akan mengatakan itu bukan mudah?

Tukar takrifan var kepada takrifan biarkan supaya gelung untuk pertama menjadi skop peringkat blok, kemudian ia boleh menjadi penumpuk. Sudah tentu tiada masalah,

Tetapi apa yang kita bincangkan hari ini ialah bagaimana untuk melaksanakan penumpuk dalam ES5. Kemudian mari kita lihat kod berikut:

function test(){
    var arr = []
    for(var i=0;i<10;i++){
        (function(j){
            arr[j]=function(){
                console.log(j);
            }
        })(i)
    }
    return arr
}

var myArr = test()

for(var j = 0; j < 10; j++){ 
    myArr[j]()
}
Salin selepas log masuk

Rakan-rakan yang berhati-hati pasti akan mendapati bahawa ini bukan sahaja menukar badan fungsi dalam gelung kepada fungsi laksana sendiri, tetapi hasil output pada masa ini iaitu Sepuluh nombor adalah output dari 0 hingga 9 dalam urutan, yang mengandungi penutupan Apabila kita mula melaksanakan kod ini, gelung kedua untuk dipanggil sepuluh kali Apabila setiap fungsi pelaksanaan sendiri dilaksanakan, fungsi pelaksanaan sendiri akan dibuat. Objek AO bagi fungsi pelaksana Terdapat atribut bernama j dalam objek AO bagi fungsi pelaksana sendiri Seperti biasa, selepas pelaksanaan fungsi pelaksana sendiri selesai, objek AOnya harus dimusnahkan, tetapi apabila myarr. [j] ( ) dilaksanakan, nama atribut j dicari dalam objek AO arr[j] di bahagian atas rantai skop, tetapi ia tidak ditemui Kemudian, kami mencari ke bawah rantai skop dan mencarinya objek AO bagi fungsi laksana sendiri, jadi apabila fungsi laksana sendiri Apabila fungsi pelaksanaan tamat, objek AOnya tidak akan dikitar semula oleh mekanisme kutipan sampah, jika tidak ralat akan dilaporkan apabila myarr[j] () dilaksanakan, dan penutupan akan dibuat pada masa ini.

Apabila fungsi disimpan secara luaran, penutupan akan dijana

Mari kita ambil contoh lain

function a(){
    function b(){
        var bbb = 234
        console.log(aaa);
    }
    var aaa = 123
    return b // b出生在a里面,但是被保存出去了
}

var glob = 100
var demo = a()
demo()
Salin selepas log masuk

Perenggan ini Kami dahulukan gunakan prapengumpulan untuk menganalisis kod Pertama, tentukan objek GO global dan cari pengisytiharan pembolehubah global sebagai nama atribut Cari perisytiharan fungsi secara global fungsi Nama digunakan sebagai nama atribut objek GO, dan nilai diberikan kepada badan fungsi. Pada masa ini ia sepatutnya GO{ glob: undefined--->100: undefined a: fa(){} }; Kemudian buat AO{ aaa: undefined--->123;b: fb(){} } untuk fungsi a, dan akhirnya prakompilkan fungsi b dalam fungsi a untuk mencipta AO{ b: undefined-- ->234} ;Susunan rantai skop pada masa ini ialah 1. AO objek fungsi b; 2. AO objek fungsi a; Apabila kita mencetak aaa dalam fungsi b, kita mulakan dari bahagian atas rantai skop Jika tiada aaa dalam objek AO fungsi b, kita akan mencari ke bawah di sepanjang rantai skop untuk mencari AO bagi fungsi peringkat kedua a. Objektifnya adalah untuk mencari nilai aaa sebagai 123 dan menghasilkan hasilnya.

如果我们没有从预编译的角度去分析就会认为此时的aaa应该会报错的,当var demo = a()执行时,当a函数执行结束,那么a对应的AO对象应该被销毁了,照常理分析当我们执行demo时作用域链此时应该会创建b的AO对象和GO对象,此时只有b的AO对象,没有a的AO对象,应该不能打印出aaa的值,但是此时aaa的值为123,则说明a的AO对象没有被销毁,那么为什么呢?原因就在于这里创建了闭包,当var demo = a()执行结束之后,垃圾回收机制会来问,a函数老兄,我看你都执行完毕了,你的运行内存是不是可以给我释放了,但是此时a函数只能无奈摇摇头说道,老哥,我也不确定我有没有执行完毕,我执行完创建了一个b,但是b又不归我管,所以我也不确定b有没有被调用,所以我也不确定我有没有执行完毕,垃圾回收机制想了想,既然你都不知道那我就不回收了,要是回收了还没执行完的就该报错了,所以此时a的AO对象就没有被回收。

补充全面一点就是:当一个函数内部的函数被保存到函数外部时,就会产生闭包。

相信通过这两个例子,你已经对闭包有了一个大概的了解,那接下来我们说一下闭包有哪些作用。

闭包的作用

    1. 实现公有变量 例如:累加器(3.js)
    1. 做缓存
    1. 可以实现封装,属性私有化
    1. 模块化开发,防止污染全局变量

我们对闭包的作用也来一个例子(3.js)

 var count = 0
 function add() {
   return count++
 }
 console.log(add());
 console.log(add());
 console.log(add());
Salin selepas log masuk

这是一段比较普通的累加的代码,但是如果我们在实习甚至是工作的时,公司要求你把累加器封装成一个模块化的代码,那么
此时,为了模块化我们尽可能避免定义全局变量,但是不定义全局变量我们如何实现呢,此时我们就可以用到闭包了;

function add() {
    var count = 0
    function a() {
      ++count
      console.log(count);
    }
    return a
  }
  var res = add()
  res()
  res()
  
  //add函数结束之后,add的AO对象没有被销毁,因为add函数执行完了之后,返回的a不知道是否被调用就形成了闭包,这样
  就能使得不使用全局变量也能封装成一个模块化的累加器。
Salin selepas log masuk

结语

那么关于闭包以及闭包的作用相关的一些个人见解就是这些,目前对于闭包也只是一些浅显的了解,后期学习之后完善过后会出后续关于闭包的相关文章,感谢您的观看,欢迎批评斧正,一起共同进步。

【相关推荐:javascript视频教程web前端

Atas ialah kandungan terperinci Apakah penutupan? Mari kita bincangkan tentang penutupan dalam JavaScript dan lihat apakah fungsinya?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:juejin.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!