闭包
-
菜鸟教程的原话: 闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。直观的说就是形成一个不销毁的栈环境。
-
菜鸟的原话:访问上层函数的作用域的内层函数就是闭包
-
大白话:一个函数内部返回一个函数
function foo(){
var a = 2;
return function bar(){
return a
}
}
foo(); // 2
这样看大概知道了,但是如果是这样勒
var Book = (function(){
var _repertory = 2020
function _subtractRepertory(){
_repertory--
}
function book(name){
this.name = name
this.getRepertory = function(){
return _repertory
}
}
book.prototype.buy = function() {
_subtractRepertory()
}
book.prototype.getName = function(){
return this.name
}
return book
})()
let book1 = new Book('js进阶') //2020
let book2 = new Book('vue进阶') // 2020
book1.getRepertory() // 2020
book2.getRepertory() // 2020
book2.buy()
book2.getRepertory() // 2019
book1.getRepertory() // 2019
简言之,实例化了两本书,库存都是2020,我买了《vue进阶》,所以库存变成了2019,但是《js进阶》我没买,但是库存也变成了2019,代码有点多。换个简单的。
function add() {
var count = 0;
return function callBack() {
count++;
console.info(count);
}
}
var add1 = add();
add1(); //1
add1(); //2
var add2 = add();
add2(); //1
add2(); //2
add函数一看就形成了闭包,但是为什么add1执行的时候记住了上一次的值,而add2一开始又忘记了,然后又记住了。
如果你只靠上面三句话,是无法快速理解的
那就再加一句话:闭包的最外层函数每次执行时,都会导致重新开辟一个空间,而内部形成闭包的函数会始终记录外部函数开辟的那一个空间
回看上一个例子
function add() { // 是最外层函数
var count = 0;
return function callBack() {
count++;
console.info(count);
}
}
var add1 = add(); // 最外层函数执行 创造了第一个空间 此时count=0
//注意此时的add1 不是等于add函数,而是等于add函数执行过后,返回的内部callBack函数,而这个callBack函数指向的是第一个空间
add1(); //1 // 第一次执行 就等于callBack在执行,其内部的count指向的是第一个空间,所以这时count 从0自加变成了1
add1(); //2 // 第二次执行 这里的callBack也是指向第一个空间的,所以count 从1变成了2
var add2 = add(); // // 最外层函数执行 创造了第二个空间,此时count=0
add2(); //1 // 同理
add2(); //2 // 同理
此时在回头看买书的例子
// 不用看
var Book = (function(){
var _repertory = 2020
function _subtractRepertory(){
_repertory--
}
function book(name){
this.name = name
this.getRepertory = function(){
return _repertory
}
}
book.prototype.buy = function() {
_subtractRepertory()
}
book.prototype.getName = function(){
return this.name
}
return book
})()
let book1 = new Book('js进阶') //2020
let book2 = new Book('vue进阶') // 2020
// 以上逻辑,不用看直接打印book1和book2,和Book
console.log(book1,book2,Book) // book,book,book 都是内部的return出来的闭包函数
// 找最外层的函数,是立即执行函数,且只执行了一次,只开辟了一个空间,所以所有的book闭包函数都是指向同一个空间的。
// 所以book1和book2,访问到的_repertory也就是书的库存都是同一个了。答案揭晓
book1.getRepertory() // 2020
book2.getRepertory() // 2020
book2.buy()
book2.getRepertory() // 2019
book1.getRepertory() // 2019
个人以为在学习闭包的时候,要特别注意 “=”,等于号很容易就麻痹你了,多来几个变量,反复等于,或者实例化。基本上人就懵了。很简单,直接打印他,看他是什么就完事。别被复杂的,很长的函数吓到。其原理往往可能会特别简单。回到菜鸟教程的原话
-
闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。直观的说就是形成一个不销毁的栈环境。
我反复阅读才发现,私有变量,有很多的函数写法,其实就是满足某种特定的需求。如果不了解 私有变量、私有方法等,诸如此类的“专业名词”,那么大概率是不会知道别人为什么这么写。
所以我觉得在学习的过程中,不要专挑难的、复杂的,又或者什么原理,定义等,在那里死记硬百度。可以先了解这里面的“目录”,或者说各种各样的模式啊,名称什么的。看看为什么会有这些东西存在,再考虑怎么实现它,然后再看看有什么问题,再优化,那么大概率,你就写出了,别人的代码。
菜鸟们,加油fly吧!!!