关于面试:彻底解决-JS-变量提升的面试题-一题一图超详细包教包会????

思维导图

变量晋升机制

一.什么是变量晋升?

  • 变量晋升示例
/* 你应该见过上面的相似代码,那你晓得这是为什么*/
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)

PS: 函数在调用时创立执行上下文对象还有其余要害的步骤作用域创立,this指向等这些内容放在前面文章讲,这样的机制有点相似变量晋升。上面的函数创立过程都会被按作相似于变量晋升来了解。

变量晋升只产生在以后作用域。比方:在页面开始加载时,只有全局作用域产生变量晋升,这时候的函数中存储的都是代码字符串。

二. 带 var 和不带 var 的区别

  • 全局作用域中不带var申明变量尽管也能够然而倡议带上 var申明变量,不带 var 的相当于给window对象设置一个属性罢了。
  • 公有作用域(函数作用域),带 var 的是公有变量。不带 var 的是会向下级作用域查找,如果下级作用域也没有那么就始终找到 window 为止,这个查找过程叫作用域链
  • 全局作用域中应用 var 申明的变量会映射到 window 下成为属性。
a = 12  // == window.a
console.log(a)  // 12
console.log(window.a) // 12

var a = b =12   // 这里的 b 也是不带 var 的。
/* 相当于*/
var a = 12;
b = 12

思考题

    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 "林一一
*/

解答

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

思路: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 也一样。

  • 问题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

  1. 经典面试题
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相似,不做剖析

三. 等号右边下的变量晋升

  • 函数右边的变量晋升
print()
function print(){
    console.log('林一一')
}
print()

很显然下面都输入了 林一一,因为带 function 的曾经进行了变量晋升

  • 匿名函数下的带 =的变量晋升
print()
var print = function() {
    console.log('林一一')
}
print()
/*输入
    Uncaught TypeError: print is not a function
/

思路:同样因为变量晋升机制带 var 的 print 是一开始值是 undefined,所以 print() 这时还不是一个函数,所以报出 类型谬误TypeError

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

  • if else 条件判断下的变量晋升
console.log(a)
if(false){
    var a = '林一一'
}
console.log(a)
/* 输入
    undefined
    undefinedN
/

在以后作用域中不论条件是否成立都会进行变量晋升

  • if else 条件判断下函数变量晋升的坑

    • 新版浏览器中,在条件判断块级作用域之外应用条件内函数

      console.log(print())
      if(true){
          function print() {
              console.log('林一一')
          }
      }
      console.log(print())
      /* 输入
          undefined
          林一一
          undefined
      /
      • 新版浏览器中,在条件判断块级作用域中应用条件内函数
      if(true) {
          console.log(print())    // ???
          function print() {
              console.log('林一一')
          }
      }
      console.log(print())
      /* 输入
          林一一
          undefined
          林一一
      /

思路:{} 大括号属于块级作用域,在 if else 中带 function 的函数同样也会先被申明和定义所以条件判断中的 print() 能够间接应用

思考题

  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

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

  • 函数名和 var 申明的变量重名
var fn = 12
function fn() {
    console.log('林一一')
}
console.log(window.fn)
fn()
/* 输入
*  12
*  Uncaught TypeError: fn is not a function
/

思路:带 var 申明的和带 function 申明的其实都是在 window 下的属性,也就是重名了,依据变量晋升的机制,JS 代码自上而下执行时此时的 fn 还只是fn = 12,所以 fn() == 12() 又是一个类型谬误 TypeError

  • 变量重名在变量晋升阶段会从新定义也就是从新赋值
console.log('1',fn())
function fn(){
    console.log(1)
}

console.log('2',fn())
function fn(){
    console.log(2)
}

console.log('3',fn())
var fn = '林一一'

console.log('4',fn())
function fn(){
    console.log(3)
}

/* 输入
*   3
*   1 undefined
*   3
*   2 undefined
*   3
*   3 undefined
*   Uncaught TypeError: fn is not a function
/

思路:同样因为变量晋升机制,fn 会被屡次从新赋值最初赋值的地址值(假如为oxfffee)为最初一个函数,所以调用 fn都只是在调用最初一个函数输入都是 3, 代码执行到var fn = '林一一',所以 fn() 其实 == 林一一() 导致类型谬误 TypeError

思考题

    1. 腾讯的一道变量晋升的面试题
var a=2;
function a() {
    console.log(3);
}
console.log(typeof a);

/* 输入
 * number
 /

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

  • 2.. 再来一道面试题
console.log(fn);
var fn = 2019;
console.log(fn);
function fn(){}

/* 输入
    fn(){}
    2019
/

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

参考

JavaScript面试题剖析之变量晋升和执行上下文

举荐浏览地址 掘金

感激浏览,我是林一一,下次见

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理