Memahami penutupan dalam kemahiran programming_javascript berfungsi javascript

WBOY
Lepaskan: 2016-05-16 15:11:31
asal
1491 orang telah melayarinya

Penutupan ialah konsep dalam pengaturcaraan berfungsi yang muncul pada tahun 1960-an Bahasa terawal untuk melaksanakan penutupan ialah Skim, yang merupakan dialek LISP. Sejak itu, ciri penutupan telah diterima pakai secara meluas oleh bahasa lain.
Takrifan ketat penutupan ialah "satu set yang terdiri daripada fungsi (persekitaran) dan pembolehubah bebas tertutupnya." dan kemudian memberikan contoh beberapa kegunaan klasik penutupan.

Apakah itu penutupan

Dalam istilah orang awam, setiap fungsi dalam JavaScript adalah penutup, tetapi secara umum, fungsi bersarang boleh mencerminkan dengan lebih baik
Untuk menunjukkan ciri penutupan, sila lihat contoh berikut:

var generateClosure = function() {
var count = 0;
var get = function() {
count ++;
return count;
};
return get;
};
var counter = generateClosure();
console.log(counter()); // 输出 1
console.log(counter()); // 输出 2
console.log(counter()); // 输出 3
Salin selepas log masuk

Dalam kod ini, terdapat kiraan pembolehubah setempat dalam fungsi generateClosure(), dengan nilai awal 0. Terdapat juga fungsi yang dipanggil get, yang meningkatkan pembolehubah kiraan dalam skop induknya, fungsi generateClosure() sebanyak 1, dan mengembalikan nilai kiraan. Nilai pulangan generateClosure() ialah fungsi get. Secara luaran, kami memanggil fungsi generateClosure() melalui pembolehubah pembilang dan memperoleh nilai pulangannya, iaitu fungsi get Kemudian kami berulang kali memanggil pembilang() beberapa kali, dan kami mendapati bahawa nilai yang dikembalikan telah ditambah sebanyak 1 setiap kali.
Mari kita lihat ciri-ciri contoh di atas Menurut pemahaman biasa tentang pemikiran pengaturcaraan imperatif, kiraan adalah pembolehubah dalam fungsi generateClosure ialah tempoh apabila generateClosure kembali daripada timbunan panggilan. pembolehubah kiraan Ruang yang digunakan akan dilepaskan. Masalahnya ialah selepas panggilan untuk generateClosure() tamat, counter() merujuk kepada pembolehubah kiraan "sudah dikeluarkan", dan bukan sahaja tiada ralat berlaku, malah kiraan diubah suai dan dikembalikan setiap kali counter() dipanggil. Apa yang berlaku?
Inilah ciri-ciri yang dipanggil penutupan. Apabila fungsi mengembalikan fungsi yang ditakrifkan di dalamnya, penutupan dijana bukan sahaja termasuk fungsi yang dikembalikan, tetapi juga persekitaran di mana fungsi itu ditakrifkan. Dalam contoh di atas, apabila fungsi dalaman mendapatkan fungsi generateClosure() dirujuk oleh pembilang pembolehubah luaran, pembolehubah tempatan pembilang dan generateClosure() adalah penutupan. Jika tidak cukup jelas, contoh berikut mungkin membantu
Anda faham:

var generateClosure = function() {
var count = 0;
var get = function() {
count ++;
return count;
};
return get;
};
var counter1 = generateClosure();
var counter2 = generateClosure();
console.log(counter1()); // 输出 1
console.log(counter2()); // 输出 1
console.log(counter1()); // 输出 2
console.log(counter1()); // 输出 3
console.log(counter2()); // 输出 2
Salin selepas log masuk

Contoh di atas menerangkan cara penutupan dijana: counter1 dan counter2 memanggil fungsi generateClosure() masing-masing, menjana dua tika penutupan dan pembolehubah kiraan yang mereka rujuk secara dalaman tergolong dalam persekitaran operasi masing-masing. Kita boleh memahami bahawa apabila generateClosure() mengembalikan fungsi get, pembolehubah dalaman bagi fungsi generateClosure() yang mendapat mungkin merujuk kepada (iaitu, pembolehubah kiraan) juga dikembalikan secara peribadi, dan salinan dijana dalam memori, dan kemudian generateClosure( ) Kedua-dua contoh fungsi yang dikembalikan, counter1 dan counter2, adalah bebas antara satu sama lain.

Tujuan penutupan

1. Fungsi panggil balik bersarang
Penutupan mempunyai dua kegunaan utama, satu adalah untuk melaksanakan fungsi panggil balik bersarang, dan satu lagi adalah untuk menyembunyikan butiran objek. Mari kita lihat contoh kod berikut untuk memahami fungsi panggil balik bersarang. Kod berikut menggunakan MongoDB dalam Node.js untuk melaksanakan fungsi mudah menambah pengguna:

exports.add_user = function(user_info, callback) {
var uid = parseInt(user_info['uid']);
mongodb.open(function(err, db) {
if (err) {callback(err); return;}
db.collection('users', function(err, collection) {
if (err) {callback(err); return;}
collection.ensureIndex("uid", function(err) {
if (err) {callback(err); return;}
collection.ensureIndex("username", function(err) {
if (err) {callback(err); return;}
collection.findOne({uid: uid}, function(err) {
if (err) {callback(err); return;}
if (doc) {
callback('occupied');
} else {
var user = {
uid: uid,
user: user_info,
};
collection.insert(user, function(err) {
callback(err);
});
}
});
});
});
});
});
};
Salin selepas log masuk

Jika anda tidak biasa dengan Node.js atau MongoDB, anda tidak perlu memahami butirannya, cuma faham logik umum. Kod ini menggunakan lapisan sarang penutupan dan setiap lapisan sarang ialah fungsi panggil balik. Fungsi panggil balik tidak akan dilaksanakan serta-merta, tetapi akan dipanggil semula oleh fungsi yang diminta selepas permintaan yang sepadan diproses. Kita dapat melihat bahawa terdapat rujukan kepada panggil balik dalam setiap lapisan sarang, dan lapisan paling dalam juga menggunakan pembolehubah uid yang ditakrifkan oleh lapisan luar. Disebabkan kewujudan mekanisme penutupan, walaupun fungsi luar telah dilaksanakan, pembolehubah yang digunakan dalam skopnya tidak akan dikeluarkan, kerana fungsi dalaman mungkin masih merujuk kepada pembolehubah ini, sekali gus merealisasikan panggilan balik tak segerak bersarang dengan sempurna.

2. Laksanakan ahli persendirian
Kami tahu bahawa objek JavaScript tidak mempunyai sifat peribadi, yang bermaksud bahawa setiap harta objek terdedah kepada dunia luar. Ini boleh menyebabkan risiko keselamatan, contohnya, jika pengguna objek secara langsung mengubah suai atribut, menyebabkan konsistensi data dalaman objek dimusnahkan, dsb. JavaScript menggunakan konvensyen untuk meletakkan garis bawah sebelum semua sifat peribadi (seperti _myPrivateProp) untuk menunjukkan bahawa sifat ini adalah peribadi dan objek luaran tidak boleh membaca atau menulisnya secara langsung. Tetapi ini hanya perjanjian tidak rasmi dengan mengandaikan bahawa pengguna objek tidak melakukan ini, adakah mekanisme yang lebih ketat? Jawapannya ya, ia boleh dicapai melalui penutupan. Mari lihat contoh sebelumnya sekali lagi:

var generateClosure = function() {
var count = 0;
var get = function() {
count ++;
return count;
};
return get;
};
var counter = generateClosure();
console.log(counter()); // 输出 1
console.log(counter()); // 输出 2
console.log(counter()); // 输出 3
Salin selepas log masuk

Kita dapat melihat bahawa hanya memanggil counter() boleh mengakses pembolehubah kiraan dalam penutupan dan menambahnya sebanyak 1 mengikut peraturan Tidak mustahil untuk mencari pembolehubah kiraan dengan cara lain. Diilhamkan oleh contoh mudah ini, kita boleh merangkum objek dengan penutupan dan hanya mengembalikan objek "aksesor" untuk menyembunyikan butiran.

Di atas ialah keseluruhan kandungan artikel ini, saya harap ia dapat membantu semua orang mempelajari dan memahami penutupan JavaScript dengan lebih baik.

Label berkaitan:
sumber:php.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