• 慕课网前端面试06--js基础-作用域和闭包


    一、题目

    • this的不同应用场景,如何取值?
    • 手写bind函数?
    • 实际开发中闭包的应用场景,举例说明?

    二、知识点

    2.1作用域和自由变量

    作用域

    • 全局作用域
    • 函数作用域
    • 块级作用域(ES6新增)

    在这里插入图片描述

    // ES6块级作用域
    if (true) {
    	let x = 100
    }
    console.log(x)  // 会报错,因为访问不到x
    
    • 1
    • 2
    • 3
    • 4
    • 5

    自由变量

    • 一个变量在当前作用域没有定义,但被使用了
    • 向上级作用域,一层一层依次寻找,直至找到为止
    • 如果到全局作用域都没找到,则报错 xx is not defined

    2.2 闭包

    • 作用域应用的特殊情况,有两种表现:
    • 函数作为参数被传递
    • 函数作为返回值被返回

    函数作为返回值被返回:

    // 函数作为返回值
    function create() {
      let a = 100
      return function () {
        // function()在这里被定义,此时a为100
        // 打印的a的值为被定义时的值
        console.log(a)
      }
    }
    let fn = create()
    let a = 200
    fn()  // 100
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    函数作为参数被传递:

    // 函数作为参数被传递
    function print(fn) {
      let a=200
      fn()
    }
    
    let a=100
    function fn() {
      // 函数fn被定义时a的值是100
      // 所以打印的a的值为100
      console.log(a);
    }
    
    print(fn) // 100
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.3 this

    • 作为普通函数
    • 使用call apply bind
    • 作为对象方法被调用
    • 在class方法中调用
    • 箭头函数
      this取什么值是在函数执行时确定的,不是在函数定义的时候确定的。
    function fn1(){
    	console.log(this)
    }
    fn1() // window
    fn1.call({ x : 100})  // {x : 100}
    const fn2=fn1.bind({x : 200})
    fn2() // {x : 200}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    bind返回新的函数去执行,bind直接调用执行。

    const zhangsan={
      name:'张三',
      sayHi(){ 
        // this 即当前对象
        console.log(this)
      },
      wait(){
        setTimeout(function(){
          // this===window
          console.log(this);
        })
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    class中,this指向当前对象。

    const zhangsan = {
      name: '张三',
      sayHi() {
        // this 即当前对象
        console.log(this)
      },
      waitAgain() {
        setTimeout(() => {
          // this 即当前对象
          console.log(this);
        })
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    箭头函数中的this取它上级作用域的值。

    class People {
      constructor(name) {
        this.name = name
        this.age = 20
      }
      sayHi() {
        console.log(this);
      }
    }
    const zhangsan = new People('张三');
    zhangsan.sayHi() // zhangsan对象
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述
    class中的this指向这个类的实例对象。

    // 创建10个`<a>`标签,点击的时候弹出来对应的序号
    let i, a
    for (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)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    点击任意<a>标签,alert出来的都是10,原因是因为i是全局变量。
    在这里插入图片描述
    修改代码:

    // 创建10个`<a>`标签,点击的时候弹出来对应的序号
    let a
    for (let i = 0; i < 10; i++) {
      // 每一个i都有一个块级作用域
      a = document.createElement('a')
      a.innerHTML = i + '<br>'
      a.addEventListener('click', function (e) {
        e.preventDefault()
        alert(i)
      })
      document.body.appendChild(a)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    2.4手写bind函数

    bind函数具有:

    • 传入的this
    • 传入的参数
    • 返回值
    // 模拟bind
    Function.prototype.bind1 = function () {
      // 将参数拆解为数组
      const args = Array.prototype.slice.call(arguments)
    
      // 获取this(数组第一项)
      const t = args.shift()
    
      // fn1.bind(...)中的fn1,
      // this指向bind函数的调用者,赋值为self变量
      const self = this
    
      // 返回一个函数
      return function () {
        return self.apply(t, args)
      }
    }
    
    function fn1(a, b, c) {
      console.log('this', this)
      console.log(a, b, c)
      return 'this is fn1'
    }
    
    const fn2 = fn1.bind({ x: 100 }, 10, 20, 30)
    const res = fn2()
    console.log(res)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    打印结果:
    在这里插入图片描述

    小结

    • 作用域和自由变量
    • 闭包:两种常见方式&自由变量查找规则
    • this
  • 相关阅读:
    洛谷P4185 离线+并查集
    单片机通识之PWM呼吸灯、变速马达等
    Codeforces Round #815 (Div. 2)(A~D1)
    从预训练损失的角度,理解语言模型的涌现能力
    Lumiprobe蛋白质定量丨QuDye 蛋白定量试剂盒
    PostgreSQL的学习心得和知识总结(八十六)|深入理解PostgreSQL数据库HOOK技术及开源hooks文档介绍
    经过CNN、LSTM训练、预测,数据集的数据为什么会被打乱?以及基于pytorch框架代码实现打乱后的恢复
    springboot大学新生小助手小程序毕业设计-附源码060917
    Django测试环境搭建及ORM查询(创建外键|跨表查询|双下划线查询 )
    python:使用随机森林回归模型进行数据预测
  • 原文地址:https://blog.csdn.net/sinat_28753227/article/details/125600383