大前端开发你可能不知道的JavaScript JavaScript

(面试) 彻底解决 JS 变量提升的面试题 | 一题一图,超详细

2021-02-26  本文已影响0人  林一一呢

推荐阅读地址

掘金 github

github 求 start😄😄

前言: 大家好,我是林一一,这是一篇关于变量提升的面试题及其概念,每一道题都基本使用画图的方式讲解来保证大家能理解的更深。让我们来开始阅读吧。

思维导图

siwei导图.png

变量提升机制

一.什么是变量提升?

/* 你应该见过下面的类似代码,那你知道这是为什么*/
console.log(a)  // undefined
var a = 10

定义:变量提升是当栈内存作用域形成时,JS代码执行前,浏览器会将带有var, function关键字的变量提前进行声明 declare(值默认就是 undefined),定义 defined(就是赋值操作),这种预先处理的机制就叫做变量提升机制也叫预定义。
在变量提升阶段:带 var 的只声明还没有被定义,带 function 的已经声明和定义。所以在代码执行前有带 var 的就提前声明,比如这里的 a 就赋值成 undefined,在代码执行过程中遇到创建函数的代码浏览器会直接跳过。

不考虑变量提升阶段的 js 运行机制相关参考JS 运行机制基础版

讲解示例

var a =12
var b = a
b = 1
function sum(x, y) {
    var total = x + y
    return total
}
sum(1, 2)
JS代码变量提升流程图.jpg

变量提升只发生在当前作用域。比如:在页面开始加载时,只有全局作用域发生变量提升,这时候的函数中存储的都是代码字符串。

PS: 函数在调用时创建执行上下文对象还有其他关键的步骤作用域创建,this指向等这些内容放在后面文章讲,这样的机制有点类似变量提升。下面的函数创建过程都会被按作类似于变量提升来理解。

二. 带 var 和不带 var 的区别

思考题

  1. 问下面分别输出什么?

    // 1
    console.log(a, b)
    var a =12, b ='林一一'
    function foo(){
    // 2
        console.log(a, b)
    // 3
        var a = b =13
        console.log(a, b)
    }
    foo()
    console.log(a, b)
    
    /* 输出:
        undefined undefined
        undefined "林一一"
        13 13
        12 13
    */
    
  2. 问下面的结果和上面的有何不同?

    console.log(a, b)
    var a =12, b = '林一一'
    function foo(){
        console.log(a, b)
    //  var a =b =13
        console.log(a, b)
    }
    foo()
    // 4
    console.log(a, b)
    
    /* 输出:
        undefined undefined
        12 "林一一"
        12 "林一一"
        12 "林一一
    */
    

解答

上面的思考题不知道你都对了没,下面让我来解答,详情看图

sikaotisc.jpg

思路:1处的 a, b 其实就是window下面的属性为 undefined。在函数内部由于变量提升机制 avar 一开始就是 undefined,b不带var 将向上级作用域查找,找到全局作用域下的林一一所以2处打印出来的就是 undefined "林一一"。随后 a =13,window.b =13,即原来 b='林一一' 变成了 b=13,打印出13, 13,最后第4处打印处12, 13。所以结合流程图,很明显知道答案

  1. 问题3,再来看一道,问下面答案是什么?
    a = 0
    function foo(){
        var a =12;
        b = '林一一'
        console.log('b' in window)
        console.log(a, b)
    }
    
    foo()
    console.log(b)
    console.log(a)
    
    /* 输出
        true
        12 "林一一"
        林一一
        0
    /
    

    思路:这是比较简单的一道题,需要注意的是函数内的 b 没有带 var,b 会一直向上查找到 window 下,发现 window 下也没有就直接给 window 设置了一个属性 window.b = '林一一',同理全局下的 a 也一样。

不带var例题.jpg
  1. 问题4,问下面答案是什么?和问题3有什么区别

    function foo(){
        console.log(a)
        a =12;
        b = '林一一'
        console.log('b' in window)
        console.log(a, b)
    }
    foo()
    /* 输出
        Uncaught ReferenceError: a is not defined
    /
    

    思路:问题4和问题3的主要区别在于第一个 console.log(a) 处,因为 a 不在函数作用域内,就会向上找 window 下的作用域,发现也没有就会直接抛出引用错误 ReferenceError

  2. 经典面试题

    fn();
    console.log(v1);
    console.log(v2);
    console.log(v3);
    function fn(){
        var v1 = v2 = v3 = 2019;
        console.log(v1);
        console.log(v2);
        console.log(v3);
    }
    /*输出
        2019
        2019
        2019
        Uncaught ReferenceError: v1 is not defined
    /
    

    思路:和问题4类似,不做分析

三. 等号左边下的变量提升

func=left.jpg

四. 条件判断下的变量提升

ifFalse.jpg iftrue.jpg

思考题

  1. 题目1,if判断语句中的变量提升
    if(!("value" in window)){
        var value = 2019; 
    }
    console.log(value); 
    console.log('value' in window); 
    
    /* 输出
        undefined
        true
    /
    

    思路:和上面所说的一样,不管条件是否成立带 var 的变量提升,当前在全局作用域 value 就是 window 的属性,所以结果显而易见输出 undefined 和 true

五. 重名问题下的变量提升

allOne.jpg fn重名.jpg

思考题

  1. 腾讯的一道变量提升的面试题
    var a=2;
    function a() {
        console.log(3);
    }
    console.log(typeof a);
    
    /* 输出
     * number
     /
    

    思路:这是一道比较简单的变量提升题,JS 代码自上而下执行时,a 被赋值成 2,输出就是 number

tenxuntongming.jpg
  1. 再来一道面试题
    console.log(fn);
    var fn = 2019;
    console.log(fn);
    function fn(){}
    
    /* 输出
        fn(){}
        2019
    /
    

    思路:这也是重名下的一道面试题,在变量提升阶段 fn由变量值声明为 undefined被修改定义为 fn函数本身 fn(){},所以第一个输出就是 fn(){},第二个输出 fn 由被赋值成 fn=12 输出12

参考

JavaScript面试题分析之变量提升和执行上下文

结束

感谢阅读,我是林一一,下次见

上一篇 下一篇

猜你喜欢

热点阅读