理解闭包作用

闭包

犀牛书:函数变量可以保存在函数作用域内 就可以叫做闭包

高级程序设计:闭包指有权访问另一个 函数作用域中的变量的函数(函数没有导出);

你不知道的javascript:当函数可以记住并访问所在的词法作用域时,就产生闭包,即使函数是在当前词发作用域之外执行

function foo(){
    let n = 0;
}
//例子一
function(){
    let n = 0;
    function bar(){
        console.log(n)
    }
}

//例子二
// 闭包
function fn(callback){
  let num = 18
  return callback(num)
}

fn(function(){
  console.log([].shift.call(arguments));
})

闭包的作用:是延长变量的生命周期

形成闭包的条件?

  1. 函数嵌套
  2. 函数导出
  3. 能够访问父函数的作用域
  4. 当函数的执行,导致函数被定义 或 抛出

闭包思考题

  1. test 里边能不能拿到n ?
  2. 为什么拿不到n?
  3. 如果我想要拿到应该怎么办
function fn(callback){
  let n = 99
  callback()
}

function test(){
  console.log(n);
}

fn(test)


//可能见得多的都是这样  和上边有稍微不一样 
function fn(callback){
  let n = 99
  return callback(n)
}

let res = fn(n => n)
console.log(res);

个人理解,解答:

1. 不能
2. 因为test 函数在当前函数体内 的 作用域  找到 n这个变量,然后就会往上一级找 也没有找到,
3. 如果想拿到,可以在callback()里边传入,然后test接收   `或者`  返回一个函数 定义  然后外边再调用,之所以可以打印到n的值  ,实际还是因为 函数还在调用 上一级的 函数作用域还没有被销毁,进而验证了  闭包的作用就是为了延长变量的生命周期

闭包的形式

1.函数的返回值是函数
function foo(fn){
    let n = 0;
    return function(){}
}

2.返回的变量是函数
function foo(){
    let n = function(){}
    return n
}
foo()

3.全局变量定义的闭包
let outter;
function foo(){
    let a = 10;
    outter = function(){
        console.log(a)
    }
}
foo();
outter()

4.函数参数的方式  个人感觉这种挺常见
let inner = function(fn){
    console.log(fn())
}

;(function(){
    let b = "local";
    let n = function(){
        return b
    }
    inner(n)
})()

5.循环赋值
function foo(){
  let arr = []
  for (let i = 0; i < 10; i++) {
    arr[i] = function(){
      console.log(i);
    }
  }
  return arr
}

let res = foo();
res.forEach(fn => {
  fn()
})

个人理解为什么闭包能延伸变量的作用域范围?

  • 因为函数每次调用都会创建一个新作用域,且子函数被使用时父级环境将被保留
  • 使用 let/const 可以将变量声明在块作用域中(放在新的环境中,而不是全局中)

出个题理解下闭包

function fun(n,o){
  console.log(o);
  return {
    fun(m){
      return fun(m,n)
    }
  }
}

//1.问 打印什么
let a = fun(0)  
a.fun(1)
a.fun(2)
a.fun(3)

//undefined 0 0 0
  • 第一个undefined不用说了 ,后边为啥是0?
    • 因为子函数被使用时父级环境(就是作用域)将被保留,然后会找到 父函数中的n ,n当时传入的是0 所以就是打印0

我们分析下作用域

//伪代码

//执行 let a = fun(0)
|-- fun(n,o)作用域
	n = 0 ,o = undefined   //内部有函数执行 此作用域被保留

	//执行a.fun(1)
	a : {
        fun(1) return fun(m,n)  //(1,0)
        //这个时候 父函数的作用域会被保留m = 1 ,然后会向上找n,找到 n = 0(这里的n就是fun函数的 第一个形参 ,不要被迷惑了)
    }
    
	//执行a.fun(2)   
	a : {
        fun(2) return fun(m,n)  //(2,0) n会向上找
    }
	
	//执行a.fun(3)   
	a : {
        fun(2) return fun(m,n) //(3,0) n会向上找
    }

改成这样子呢?

function fun(n,o){
  console.log(o);
  return {
    fun(m){
      return fun(m,n)
    }
  }
}

//2.问 打印什么
let b = fun(0).fun(1).fun(2).fun(3);  
//undefined 0 1 2

我们也用伪代码分析下作用域

//伪代码
//执行fun(0)
function(n,o){    
    //n = 0 , o = undefined  该作用域变量没有被销毁
    console.log(o) //打印 undefined
    
    //执行fun(0).fun(1)
    function(n,o){
        //n = 1,o=0
           console.log(o) //打印 0
        
        //执行fun(0).fun(1).fun(2)
        function(n,o){
            //n = 2 ,o = 1
            console.log(o) //打印 1
            
            //执行fun(0).fun(1).fun(2).fun(3)
            function(n,o){
                //n = 3 ,o = 2
                console.log(o) //打印 2
            }(3,2)
            
        }(2,1) //此时上一个作用域里找到了 n = 1 
        
    }(1,0) //此时上一个作用域里找到了 n = 0
    
}(0)

  • 一层一层嵌套 上一个作用域还没有被销毁

看到这里是不是可以理解为 闭包的作用 呢 ? 就是延长变量的生命周期,

为什么会延长?因为子函数在使用时,父函数的作用域不会被销毁

再改一下

function fun(n,o){
  console.log(o);
  return {
    fun(m){
      return fun(m,n)
    }
  }
}

let c = fun(0).fun(1);
c.fun(2);
c.fun(3);

  • 看到这题应该可以直接出答案了
  • undefine 0 1 1
总结

闭包的作用 呢 ,就是延长变量的生命周期

为什么会延长?因为子函数在使用时,父函数的作用域不会被销毁

形成闭包的条件?

  1. 函数嵌套
  2. 函数导出
  3. 能够访问父函数的作用域
  4. 当函数的执行,导致函数被定义 或 抛出
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值