变量声明提升和函数声明提升(含笔试题)

364 阅读5分钟

1. 变量声明提升和函数声明提升(重点规则)

//var和函数有声明提升,const/let没有
1. 从概念的字面意义上说,“变量提升”意味着变量和函数的声明会在物理层面移动到代码的最前面,但这么说并不准确。
2. 实际上变量和函数声明在代码里的位置是不会动的,而是在编译阶段被放入内存中。
    
3.JS 在执行任何代码段之前,将函数声明放入内存中的优点之一是,你可以在声明一个函数之前使用该函数,
     //正常思维(先声明,后调用)
     //即使我们在定义这个函数之前调用它,函数仍然可以工作。这是因为在 JavaScript 中**执行上下文**的工作方式造成的。
     
4. 变量提升也适用于其他数据类型和变量。变量可以在声明之前进行初始化和使用。但是如果没有初始化,就不能使用它们。
    //JavaScript 只会提升声明,不会提升其初始化。如果一个变量先被使用再被声明和赋值的话,使用时的值是 undefined
    //如果你先赋值、再使用、最后声明该变量,使用时能获取到所赋的值
    
5. 函数和变量相比,会被优先提升。这意味着函数会被提升到更靠前的位置,函数提升时,参数也会也会提前(变量值和对象在堆中的内存地址值)。
6. 函数表达式不会被提升:
        //例1:
        notHoisted(); // TypeError: notHoisted is not a function
        var notHoisted = function() {
          console.log('bar');
        };


        //例2:
        function test(x) {
            console.log(x)//1
            console.log('x')//x
        }
        const p = 1
        const p2 = test(p)
        console.log(p) // -> 1
        console.log('p') // -> p
        console.log(p2) // -> undefined
        //结果:
        // 1
        // x
        // 1
        // p
        // undefined
 7. 函数提升优先级高于变量提升,且不会被同名变量声明覆盖,但是会被变量赋值后覆盖。而且存在同名函数与同名变量时,优先执行函数。同名函数会被覆盖。
      //例1:
         console.log(a); //f a() 
         console.log(a()); //1 
         var a=1; 
         function a(){ 
             console.log(1); 
         } console.log(a); //1 
         a=3 
         console.log(a()) //a not a function
8. window全局作用域和fn函数作用域,在打印变量时,会先在fn函数作用域里面查找,因为在执行fn函数时,在函数内部也会先进行变量提升.
9.  同一作用域下存在多个同名函数声明,后面的会替换前面的函数声明

2. 变量声明和赋值

console.log(num); // Returns undefined
//变量声明
var num;
//变量赋值
num = 6;

3. 函数声明和调用

//函数声明
function catName(name) {
    console.log("我的猫名叫 " + name);
}
//函数调用
catName("Tigger");

4. 变量提升和函数提升笔试题

1.说出下面运行的结果,解释原因。
1function test(person) {  
    person.age = 26  
    person = {  
    name: 'hzj',  
    age: 18  
    } 
    return person  
    }   
    const p1 = {  
    name: 'fyq',  
    age: 19  
    }   
    const p2 = test(p1)  
    console.log(p1) // -> ?  
    console.log(p2) // -> ?  

    结果:
        p1:{name: “fyq”, age: 26}  
        p2:{name: “hzj”, age: 18}  

    原因: 
        //在函数传参的时候传递的是对象在堆中的内存地址值,test函数中的实参person是p1对象的内存地址,
        //通过调用person.age = 26确实改变了p1的值,但随后person变成了另一块内存空间的地址,
        //并且在最后将这另外一份内存空间的地址返回,赋给了p2。



  
2. 说出下面运行的结果,解释原因
    function test(x) {
        console.log(x)//1
        console.log('x')//x
    }
    const p1 = 1
    const p2 = test(p1)
    console.log(p1) // -> 1
    console.log('p1') // -> p1
    console.log(p2) // -> undefined
 结果:
     1
     x
     1
     p
     undefined
     
 原因:
      //函数表达式不会被提升
      //函数提升优先级高于变量提升,且不会被同名变量声明覆盖,但是会被变量赋值后覆盖。
      //而且存在同名函数与同名变量时,优先执行函数。
      
      
3. 说出下面运行的结果,解释原因
  1、第一题
  
  var a = 4
  function fn () {
    console.log(a)
    var a = 5
  }
  fn()
  输出结果:undefined
  //说明: 在上面这段代码中有两个作用域,window全局作用域和fn函数作用域,
          //在打印变量a时,会先在fn函数作用域里面查找,
          //因为在执行fn函数时,在函数内部也会先进行变量提升,所以最终的打印结果为undefined。
//代码实际的执行顺序为:
  var a = 4
  function fn () {
    var a;
    console.log(a); //undefined
    a = 5
  }
  fn()

  2、第二题

  function a() {}
  var a;
  console.log(typeof a)
  输出结果:function

  function a() {}
  var a = 1;
  console.log(typeof a)
  输出结果:number
  //说明:函数提升优先级高于变量提升,且不会被同名变量声明时覆盖,但是会被同名变量赋值后覆盖。

  3、第三题

  console.log(typeof a)
  function a() {}
  var a = 1;
  输出结果:function
  //说明: 函数提升的优先级高于变量提升。

  4、第四题
  
  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


5、第五题
//说明:同一作用域下存在多个同名函数声明,后面的会替换前面的函数声明,函数表达式不会被提升
//说明:函数提升优先级高于变量提升,且不会被同名变量声明覆盖,但是会被变量赋值后覆盖。而且存在同名函数与同名变量时,优先执行函数。
console.log (foo);
var foo = function () {
    console.log('foo1');
}
foo();
var foo = function () {
    console.log('foo2');
}
foo();
//结果:
    ƒ () {
        console.log('foo2');
        }
    foo1
    foo2



//Example1(变量提升)
foo;
var foo = function () {
    console.log('foo1');
}
foo();
var foo = function () {
    console.log('foo2');
}
foo();
//结果:
    foo1
    foo2


//Example2(同名函数声明提升覆盖)
//说明:同一作用域下存在多个同名函数声明,后面的会替换前面的函数声明,函数表达式不会被提升。
foo();
function foo() {
    console.log('foo1');
}
foo();
function foo() {
    console.log('foo2');
}
foo();
//结果:
    foo2
    foo2
    foo2


//Example3(函数变量同名,变量赋值会覆盖函数声明)
//说明:函数提升优先级高于变量提升,且不会被同名变量声明覆盖,但是会被变量赋值后覆盖。而且存在同名函数与同名变量时,优先执行函数。
foo();
var foo = function() {
    console.log('foo1');
}
foo();
function foo() {
    console.log('foo2');
}
foo();
//结果:
    foo2
    foo1
    foo1