【经典面试题】作用域链 与 函数中的this指向

下列函数中 this 的指向 :

        let obj = {
            name:'张三',
            age:18,
            sayHi(){
                let fn1 = function(){
                    console.log(this)
                }
                fn1()

                let fn2 = ()=>{
                    console.log(this)
                }
                fn2()
            },
            eat:()=>{
                let fn3 = function(){
                    console.log(this)
                }
                fn3()
                
                let fn4 = ()=>{
                    console.log(this)
                }
                
                fn4()
            }
        }
        obj.sayHi()
        obj.eat()

解题辅助知识点

1 . 作用域

变量作用域 : 变量起作用的范围

  1. 全局作用域(全局变量) :在函数外外面声明,页面任何地方都可以使用
  2. 局部作用域(局部变量) : 在函数内部声明,只能在函数内部使用
  3. 块级作用域 : 在大括号里面声明的变量(分支和循环),只能在大括号内部使用
      //1.全局变量 :   全局作用域
      let num = 10

      function fn () {//函数的形参相当于在函数内部声明变量 : 局部变量
        //2.局部变量: 局部作用域(函数内部作用域)
        let age = 30
        console.log(age)
      }
      fn()

      for (let i = 1; i <= 10; i++) {
          //3.块级变量:块级作用域(只能在大括号内部使用)
        console.log(i)
      }

2 . 作用域链

原理 : 默认情况下,js代码处于全局作用域(0级),当我们声明一个函数的时候,就会开辟一个局部作用域. 函数里面也可以声明函数,就会又形成局部作用域(2级),以此类推就会形成作用域链

      //全局作用域(0级)
      let num = 10

      function fn () {
        //局部作用域(1级)
        let num = 20
        console.log('1级作用域' + num)//20

        function fn1 () {
          //局部作用域(2级)
          let num = 30
          console.log('2级作用域' + num)//30
        }
        fn1()
      }

      fn()

      console.log('0级作用域' + num)//10

变量在作用域链中的访问规则:就近原则

  • 当你在某个作用域访问变量的时候,会先看当前作用域有没有声明。如果有则访问当前作用域的变量。没有就找上级,上级也没有就继续往上。直到作用域最顶端(0级),如果0级也没有,则程序会报错。 xxx is not defined

3 . 函数中的this指向

function函数this指向: 谁‘调用’我,我就指向谁 (取决于调用,与声明无关)

  1. 普通函数 : 函数名() this 指向 window
  2. 对象方法 : 对象名.方法名() this 指向对象
  3. 构造函数 : new 函数名() this 指向 new 创建的实例对象

箭头函数中的this : 谁‘声明’我,我就指向谁

  • 真正的含义 : 箭头函数没有this
  • 箭头函数本身是没有this的,本质是通过作用域链,访问上一级的this
      //0级作用域链
      //1.普通函数
      let fn = () => {                                                                   
        //1级作用域链
        console.log(this)
      }
      fn() //window

      //2.对象的方法
      let obj = {
        name: '张三',
        age: 20,
        eat () {//function(){}
          //1级作用域链
          console.log(this)//obj
          let fn = () => {
            //2级作用域链
            console.log(this)//obj
          }
          fn()
        },
        learn: () => {
          //1级作用域链 : this访问0级
          console.log(this)//window
        }
      }
      obj.eat() //obj  function函数的this取决于调用
      obj.learn() //window  箭头函数跟调用没关系,永远都是访问上级作用域this

解题思路

  1. sayHi() 是对象的方法, 在1级作用域链, this 指向 obj
  2. f1() 在2级作用域链, 但是 function 函数取决于调用, fn1()这是普通函数调用, this 指向 window
  3. fn2 = ()=>{} 在2级作用域链, 箭头函数访问上级作用域也就是 sayHi() , this 指向 obj
  4. eat:()=>{} 在1级作用域链,但是尖头函数访问上一级作用域0级, this 指向 window
  5. fn3 = function(){} 在2级作用域链, function 函数取决于调用, fn3()这是普通函数调用, this 指向 window
  6. fn4 = ()=>{} 在2级作用域链, 箭头函数访问上级作用域也就是 eat:()=>{} , this 指向 window
        let obj = {
            name:'张三',
            age:18,
            sayHi(){
                //1级链   this:  obj

                let fn1 = function(){
                    //2级链 ; function函数取决于调用  fn1()这是普通函数调用
                    console.log(this)//window
                }
                fn1()

                let fn2 = ()=>{
                    //2级链 :  箭头函数访问上级  1级this -> obj
                    console.log(this)//obj
                }
                fn2()
            },
            eat:()=>{
                //1级链  this:window
                let fn3 = function(){
                    //2级链  function函数取决于调用  fn3()这是普通函数调用
                    console.log(this)//window
                }
                fn3()

                let fn4 = ()=>{
                    //2级链:  箭头函数访问上级  1级this -> window
                    console.log(this)//window
                }
                
                fn4()
            }
        }
        obj.sayHi()
        obj.eat()

答案 :

f1 : window 
f2 : obj
f3 : window
f4 : window

你可能感兴趣的:(javascript,前端,typescript,面试)