资讯专栏INFORMATION COLUMN

js函数声明提升与变量提升

Rindia / 3129人阅读

摘要:在编译阶段,函数声明和变量声明都会被先处理置于执行环境的顶部,且赋值会被留在原地,这个过程称之为提升。另外函数声明提升不会被变量声明覆盖,但会被变量赋值覆盖。

看到相关的前端面试题,总结一下知识点,大神请飘过。
JS在编译阶段,函数声明和变量声明都会被先处理置于执行环境的顶部,且赋值会被留在原地,这个过程称之为提升。
举个简单例子:

console.log(i);
var i = 1;
function fn () {
  console.log(2)
}

实际上代码顺序是这样的:

 function fn () {
  console.log(2)
}
var i;
console.log(i);
i = 1;
一、变量提升

变量声明在编译阶段被处理,而变量赋值则留在原地等待执行。

console.log(i);   // undefined
var i = 1;
console.log(i);   // 1

相当于:

var i;
console.log(i);   // 由于i只声明未赋值,输出undefined
i = 1;
console.log(i)    // i已赋值,输出1

一道测试题

  var age = 10;
  function person () {
      age = 100;
      console.log(age);  // 100
      var age;
      console.log(age)  // 100
  }
  person();
  console.log(age);   // 10
二、函数提升

解析器在解析时对函数声明与函数表达式有着不同的优先级,实际上编译阶段函数声明会先于变量被提升,并使其在执行任何代码之前可访问,函数表达式实际上是变量声明的一种,因此函数声明提升优于函数表达式

console.log(fn(1));    // 1
function fn (a) {
    return a;
}

如上面的代码,由于函数声明被置于执行环境顶部,即使调用函数的代码在声明函数之前也可以正确访问。再看函数表达式的例子:

console.log(fn(1));
var fn = function (a) {
    return a;
}

// 相当于

var fn;
console.log(fn(1));
fn = function (a) {
  return a;
}
// fn is not a function

上面的例子之所以报错,是因为变量fn声明后还未对函数引用。
另外函数声明提升不会被变量声明覆盖,但会被变量赋值覆盖。
变量未赋值的例子:

  function fn(){
    console.log(1);
  }
  var fn;
  console.log(fn);    // 由于后一个fn只声明未负值,因此输出的是函数fn
  

变量赋值的例子:

  function fn(){
    console.log(1);
  }
  var fn = function () {
      console.log(2)
  };
  fn();    // 2
  
  // 相当于
  
  function fn(){
    console.log(1);
  }
  var fn;
  fn = function () {
      console.log(2)
  };
  fn();    // 2(因为声明的函数fn被后一个已引用函数的变量fn所覆盖,因此输出2)
  

再来点:

  fn();
  var fn = function () {
    console.log(1);
  }
  fn();
  function fn () {
    console.log(2);
  }
  var fn;
  fn();
  // 依次输出2,1,1
  

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93196.html

相关文章

  • js变量提升函数提升的机制

    摘要:所谓变量提升,提升就是为了事先声明变量。变量提升之后,但其赋值还是留在原本的位置等运行到了之后动态赋值,而函数提升之后直接相当于在代码里抽空了。搞明白这个例子也就搞懂了作用域中变量和函数是怎么提升的。 问题 showImg(https://segmentfault.com/img/bVJ614?w=222&h=165); 在这个例子中它应该输出什么?输出的结果是6。 showImg(h...

    fasss 评论0 收藏0
  • ES6 变量作用域提升变量的生命周期详解

    摘要:不同的是函数体并不会再被提升至函数作用域头部,而仅会被提升到块级作用域头部避免全局变量在计算机编程中,全局变量指的是在所有作用域中都能访问的变量。 ES6 变量作用域与提升:变量的生命周期详解从属于笔者的现代 JavaScript 开发:语法基础与实践技巧系列文章。本文详细讨论了 JavaScript 中作用域、执行上下文、不同作用域下变量提升与函数提升的表现、顶层对象以及如何避免创建...

    lmxdawn 评论0 收藏0
  • 5分钟深入了解js变量提升

    摘要:对于大多数开发者来说,变量提升可以说是一个非常常见的问题,但是可能很多人对其不是特别的了解。如果说拥有和一样的变量提升效果的话,那么应该是输出。而和它们的变量提升的效果是一样的,也都存在着临死性死区的概念。 对于大多数js开发者来说,变量提升可以说是一个非常常见的问题,但是可能很多人对其不是特别的了解。所以在此,我想来讲一讲。 先从一个简单的例子来入门: a = 2; var a; ...

    tinysun1234 评论0 收藏0
  • JS变量生命周期:为什么 let 没有被提升

    摘要:请注意,就变量生命周期而言,声明阶段与变量声明是不同的概念。提升在生命周期中无效的原因如上所述,提升是变量在作用域顶部的耦合声明和初始化阶段。然而,生命周期分离声明和初始化阶段。解耦消除了的提升期限。 为了保证的可读性,本文采用意译而非直译。 提升是将变量或函数定义移动到作用域头部的过程,通常是 var 声明的变量和函数声明function fun() {...}。 当 ES6 引入l...

    hoohack 评论0 收藏0
  • JS变量生命周期:为什么 let 没有被提升

    摘要:请注意,就变量生命周期而言,声明阶段与变量声明是不同的概念。提升在生命周期中无效的原因如上所述,提升是变量在作用域顶部的耦合声明和初始化阶段。然而,生命周期分离声明和初始化阶段。解耦消除了的提升期限。 为了保证的可读性,本文采用意译而非直译。 提升是将变量或函数定义移动到作用域头部的过程,通常是 var 声明的变量和函数声明function fun() {...}。 当 ES6 引入l...

    Steven 评论0 收藏0

发表评论

0条评论

Rindia

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<