作用域和闭包

本文详细解析了JavaScript中的闭包与作用域概念,包括变量提升、自由变量、作用域链等关键知识点,同时介绍了闭包在实际开发中的应用,如封装变量和收敛权限。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作用域和闭包

  1. 对变量提升的理解

    • 变量定义
    • 函数声明(注意和函数表达式的区别)
  2. 说明 this 几种不同的使用场景

  3. 创建 10 个<a>标签,点击的时候弹出对应的序号

    var i
    for (i = 0; i < 10; i++) {
      ;(function(i) {
        var a = document.createElement('a')
        a.innerHTML = i + '<br>'
        a.addEventListener('click', function(e) {
          e.preventDefault()
          alert(i) // 自由变量,要去父作用域获取值
        })
        document.body.appendChild(a)
      })(i)
    }
    
  4. 如何理解作用域

    • 自由变量
    • 作用域链,即自由变量的查找
    • 闭包的两个场景
  5. 实际开发中闭包的应用

    //闭包实际应用中主要用于封装变量,收敛权限
    function isFirstLoad() {
      var _list = []
      return function(id) {
        if (_list.indexOf(id) >= 0) {
          return false
        } else {
          _list.push(id)
          return true
        }
      }
    }
    //使用
    var firstLoad = isFirstLoad()
    firstLoad(10) //true
    firstLoad(10) //false
    firstLoad(20) //true
    firstLoad(20) //false
    //你在isFirstLoad函数外面,不可能修改_list的值
    

知识点

  1. 执行上下文

    • 范围:一段<script>或者一个函数

    • 全局:变量定义、函数声明 一段<script>

    • 函数:变量定义、函数声明、this、arguments 函数

    • PS:注意"函数声明"和"函数表达式"的区别

      console.log(a) //undefined
      //下一行为函数表达式
      var a = 100
      
      fn('zhangsan') //'zhangsan' 20
      //以下为函数声明
      function fn(name) {
        age = 20
        console.log(name, age)
        var age
      }
      
  2. this

    • this 要在执行时才能确认值,定义时无法确认

      var a = {
        name: 'A',
        fn: function() {
          console.log(this.name)
        }
      }
      //上面是定义时,下一行为执行时
      a.fn() //this === a
      a.fn.call({ name: 'B' }) //this ==={name:'B'}
      var fn1 = a.fn
      fn1() //this === window
      
    • 作为构造函数执行

      function Foo(name) {
        this.name = name
      }
      var f = new Foo('zhangsan')
      
    • 作为对象属性执行

      var obj = {
          name = 'A',
          printName: function(){
              console.log(this.name);
          }
      }
      obj.printName();
      
    • 作为普通函数执行

      function fn() {
        console.log(this) //this === window
      }
      fn()
      
    • call、apply、bind
      说明:call ()和 apply()作用一样,但是 call()可以接收任何类型的参数,而 apply()只能接收数组参数。

       //call
       function fn1(name, age) {
         alert(name)
         console.log(this) //this为{x:100}
       }
       fn1.call({ x: 100 }, 'zhangsan', 20)
       //apply
       function fn2(name, age) {
         alert(name)
         console.log(this) //this为{x:100}
       }
       fn2.apply({ x: 100 }, ['zhangsan', 20])
       //bind
       var fn3 = function(name, age) {
         alert(name)
         console.log(this) //this为{y:200}
       }.bind({ y: 200 })
       fn3('zhangsan', 20)
      
  3. 作用域

    • 没有块级作用域

      if (true) {
        var name = 'zhangsan'
      }
      console.log(name)
      
    • 只有函数和全局作用域

      var a = 100
      function fn() {
        var a = 200
        console.log('fn', a)
      }
      console.log('global', a)
      fn()
      
    1. 作用域链

      var a = 100
      function fn() {
        var b = 200
        //当前作用域没有定义的变量,即"自由变量"
        console.log(a)
        console.log(b)
      }
      fn()
      
      var a = 100
      function F1() {
        var b = 200
        function F2() {
          var c = 300
          console.log(a) //a是自由变量
          console.log(b) //b是自由变量
          console.log(c)
        }
        F2()
      }
      F1()
      
  4. 闭包

    • 函数作为返回值

       function F1() {
         var a = 100
         //返回一个函数(函数作为返回值)
         return function() {
           console.log(a)
         }
       }
       //f1得到一个函数
       var f1 = F1()
       var a = 200
       f1() //100
      
    • 函数作为参数传递

       function F1() {
         var a = 100
         //返回一个函数(函数作为返回值)
         return function() {
           console.log(a) //自由变量,父作用域寻找
         }
       }
       //f1得到一个函数
       var f1 = F1()
      
       function F2(fn) {
         var a = 200
         fn()
       }
       F2(f1) //100,a的值跟执行作用域无关,与声明作用域有关
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值