前端面试——变量提升?函数提升?

回答侧重点:
1:什么是变量提升?
JavaScript 引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,包括函数,都会被提升到代码的头部(作用域顶端),这就叫做变量提升(hoisting)。

1:预解析阶段:在预解析阶段,js会对以var声明的变量,和function开头的语句块进行提升,将var声明的变量和function 提升至代码的最前面。
2:需要注意的是,function整体提升,var 声明的变量只提升变量声明,并不会在提升的同时进行赋值操作
3:然后是执行阶段

注:这意味着无论作用域中的声明出现在什么地方,都将在代码本身被执行前首先进行处理,可以将这个过程形象地想象成所有的声明(变量和函数)都会被“移动”到各自作用域的最顶端,这个过程被称为提升。
举例简单说明:

function test () {
    console.log(a);  //undefined  表示变量已经声明,但是没有赋值
    var a = 123; 
};
test();

上述代码实际的执行过程为:

function test () {
    var a;//变量a在定义赋值123之前,进行了提前的声明,提升到了最顶部,但是未定义,所以为undefined
    console.log(a);
    a = 123;
}
test();

2:函数提升?
javascript中不仅仅是变量声明有提升的现象,函数的声明也是一样;具名函数的声明有两种方式:

1. 函数声明式   声明会被提前,并且不能被立即调用
2. 函数字面量式(函数表达式)   是在代码执行阶段才去创建对应的函数表达式的,所以不会提前
3. 函数声明和变量声明会被提前提升,而像下面的赋值语句或者表达式产生的函数对象的创建会在后面的代码执行阶段进行,

前端面试——变量提升?函数提升?_第1张图片

//函数声明式
function bar () {}
//函数字面量式 
var foo = function () {}
console.log(foo1); // [Function: foo1]
foo1(); // foo1
console.log(foo2); // undefined  不会报错 未定义
foo2(); // TypeError: foo2 is not a function
function foo1 () {
	console.log("foo1");
};
var foo2 = function () {
	console.log("foo2");
};

3:多个函数同名提升规则: 都提升,但是后面的函数会覆盖掉前面函数

func1();  //输出  我是后声明的函数
function func1(){
   console.log('我是先声明的函数');
}
function func1(){
   console.log('我是后声明的函数');
}
实际提升后的代码
function func1(){
   console.log('我是先声明的函数');
}
function func1(){
   console.log('我是后声明的函数');
}
func1();
 函数名也是变量,后面的会覆盖前面。

4:变量名和函数名相同提升规则:如果有变量和函数同名,会忽略掉变量,只提升函数
(函数优先规则)

console.log(foo); //输出function foo(){}

function foo(){
}
var foo = 2;
console.log(foo); //输出 2
----------
//提升后的代码 可以看到声明函数优先变量,而且同名可以覆盖!
function foo{}
console.log(foo);
foo = 2;
console.log(foo);

5:变量提升是区分不同的作用域的

var num = 123;
 function test(){
     console.log(num);
     var num = 10;
 }
 test(); //输出undefined; 

----------

模拟变量提升后的代码
  var num;
function test(){
var num
   console.log(num); //函数内部声明了num,但是没赋值。因为在函数内部声明了num,所以函数会使用它内部声明的num,而不会去全局中找  
   num = 10;
  }
num = 123;

前端面试——变量提升?函数提升?_第2张图片
最后附上几道经典的前端变量提升面试题:
1:

console.log(v1);
var v1 = 100;
function foo() {
    console.log(v1);
    var v1 = 200;
    console.log(v1);
}
foo();
console.log(v1);
// undefined  undefined 200  100

2:

  console.log(a)
  a();
  var a=3;
  function a (){
    console.log(10)
  }
  console.log(a)
  a=6;  //此时a已经不是一个函数了,所以会报错
  a()
  //输出结果:function a () {console.log()}  10 3  TypeError 
	1.函数声明优先于变量声明,所以,刚开始,a就是 function a(){alert(10)} ,就会看到这个函数。
	2. a(),执行函数,就是出现 10
	3.执行了 var a=3; 所以 console.log(a)就是显示 3
	4.由于 a不是一个函数了,所以往下在执行到 a()的时候, 报错。

在这里插入图片描述
3:

  var a = 1;
  function b() {
    a = 10;
    return;
    function a() {}
  }
  b();
  console.log(a); // 打印1
var a = 1; // 定义一个全局变量 a
function b() {
    // 首先提升函数声明function a () {}到函数作用域顶端, 然后function a () {}等同于 var a =  function() {};最终形式如下
    var a = function () {}; // 定义局部变量 a 并赋值。
    a = 10; // 修改局部变量 a 的值,并不会影响全局变量 a
    return;
}
b();
console.log(a); // 打印全局变量 a 的值:1

4:

  function foo(){
    function bar() {  //两个函数bar都会被提升到作用域下的顶部,同名的会进行替换,所以下一个是return 8
      return 3;
    }
    return bar();
    function bar() {
      return 8;
    }
  }
  console.log(foo());  //打印8 

5:(注意和上题区分)

console.log(foo());  //打印3 
function foo() {
   var bar = function() {
      return 3;
   };
   return bar();
   var bar = function() {
      return 8;
   };
}

6:(注意:容易迷惑,看仔细返回的是什么)

  function parent() {
    var hoisted = "I'm a variable";
    function hoisted() {
      return "I'm a function";
    }
    return hoisted();
  }
  console.log(parent());  // “TypeError: hoisted is not a function”

7:

你可能感兴趣的:(变量提升,函数提升,前端面试)