• [JavaScript初级面试]4. JS基础-作用域和闭包


    题目

    • this的不同使用场景,如何取值
    • 手写bind函数
    • 闭包在开发中的使用场景,举例说明
    • 创建10个<a>标签,点击的时候弹出对应的序号

    作用域

    全局作用域

    函数作用域

    块级作用域

    代码块中{}

    自由变量

    产生:使用了一个在当前作用域没有定义的变量A
    一个变量A在当前作用域没有定义,但被使用了;
    这个变量A就是自由变量

    确认自由变量的值,需要在当前作用域向上级作用域,一层一层寻找,直到找到为止;如果到了全局作用域,还没有找到,则报错xx is not defined
    image
    最内层的框中a,a1,a2都是自由变量

    闭包

    有两种情况:

    1. 函数作为函数参数
      image
    2. 函数作为函数返回值
      image

    核心点:

    1. 因为函数拥有自己的作用域,使用函数的位置,如果与函数定义的位置不同,并且函数内部还存在自由变量, 则产生闭包(包住一个不属于当前作用域的变量)
    2. 作用域链形成时,函数作用域的父级作用域不是调用函数时所在的作用域,而是在定义函数时所在的作用域
    3. 在查找自由变量的值时,应该在函数定义所在的作用域为起始点查找;而不是在函数被调用的地方所在的作用域查找(沿着函数作用域链查找)

    this

    this的取值,不是在定义时确定的,而是在调用时确定的。(自由变量的值是在定义时确定的)

    • 构造函数中
      image
      创建空对象{},this变量;this变量指向空对象;给this添加属性(构造赋值过程);返回this
    • class
      image
    • bind, apply, call
    func.call(this, arg1, arg2);
    func.apply(this, [arg1, arg2])
    func.bind(this) // bind 返回新函数
    

    image

    • 普通函数
    • 箭头函数
      箭头函数中this永远绑定定义箭头函数时所在作用域的this。很直观
      image

    解答

    手写bind函数

    函数实例的隐式原型就是Function的显式原型

    Function.prototype.bind = function(){
      // 把参数拆解为数组
      const args = Array.prototype.slice.call(arguments)
      // 获取this,数组第一项; 在参数数组中剔除this
      const t = args.shift()
      // this 是 fn1.bind()里的fn1
      const self = this
      // bind会返回一个函数
      return function(){
        return self.apply(t, args)
      }
    }
    

    闭包应用举例

    隐藏数据,只提供API

    function createCache(){
      const data = {} //闭包中的自由变量,被隐藏,外界无法访问
      return {
        set: function(key, val){
          data[key] = val
        },
        get: function(key){
          return data[key]
        }
      }
    }
    

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

    方法一:

    let a
    for(let i=0; i<10; i++){
      a = document.createElement('a')
      a.innerHTML = i + '<br>'
      a.addEventListener('click', function(e){
        e.preventDefault()
        alert(i)
      })
      document.body.appendChild(a)
    }
    
    

    方法二:

    let i, a
    for(i=0; i<10; i++){
      a = document.createElement('a')
      a.innerHTML = i + '<br>'
      a.addEventListener('click', (e) => {
        e.preventDefault()
        alert(i)
      })
      document.body.appendChild(a)
    }
    

    本文来自博客园,作者:Max力出奇迹,转载请注明原文链接:https://www.cnblogs.com/welody/p/15214484.html

    如果觉得文章不错,欢迎点击推荐

  • 相关阅读:
    Completely disable mousewheel on a WinForm
    C# Form内存回收
    解锁用户
    CentOS7+JDK8编译Hadoop2.6.4
    网址收藏
    pvresize
    Linux crontab 命令格式与详细例子
    在CentOS 7中安装与配置JDK8
    Disable SELinux CentOS 7
    Python3标准库:math数学函数
  • 原文地址:https://www.cnblogs.com/welody/p/15214484.html
Copyright © 2020-2023  润新知