章节索引 :

变量提升

变量提升是 JavaScript 在运行时的一种机制。

在代码被执行前,JavaScript 会做一些准备工作,其中会准备一个执行上下文,也就是代码的执行时的环境,如 绑定this、准备变量等。

变量提升这一特性就是在准备执行上下文时进行的,这一特性也是和执行上下文相关的最常在面试中出现的内容。

1. 表现

console.log(number); // 输出:undefined

var number = 1;

console.log(number); // 输出:1

图片描述

这段代码先输出了 undefined 再输出了 1

说明 number 变量在第一行输出之前就已经存在了,只不过没有被赋值,因为如果变量不存在,访问变量会抛出异常:ReferenceError: 变量 is not defined

可是在第一次使用 number 之前并没有声明过变量,却可以被访问到,出现这个表现就是因为变量提升的特性。

在生成执行上下文阶段,会把变量都收集起来,事先进行声明,需要注意的是,这个特性只会声明变量,而不会初始化,即变量的值都会是 undefined

根据这个规则,上面这段代码在执行时可以理解成是这样的:

var number;

console.log(number);

number = 1;

console.log(number);

需要注意的是,如果没有使用 var 关键字声明变量,是不会进行提升处理的。

console.log(number);

number = 1;

console.log(number);

图片描述

这样就会抛出变量不存在的异常。

2. 函数提升

函数也会提升,函数的提升会把整个函数放到最前。

fn('咕咕咕');

function fn(str) {
  console.log(str);
}

图片描述

这段代码可以被正常执行,函数也能被正常调用,因为在生成执行上下文阶段,整个函数会提升到最前面。

这个规则只对函数声明的方式声明的函数有效,如果使用的是函数表达式,那就会走变量提升的规则。

console.log(fn); // 输出:undefined
fn('咕咕咕'); // 抛出异常 TypeError: fn is not a function

var fn = function(str) {
  console.log(str);
};

可以看到 fn 能被访问到,已经声明了,但不能作为函数调用,这说明 fn 走了变量提升的机制。

在执行上下文生成的阶段,函数会比变量更早的进行提升,也就是说函数相比变量,更加靠前。

函数在调用时也会生成函数级别的执行上下文,这也就意味着提升这个特性也会在函数执行前发生

3. 小结

在 ES6 中和提升相关的内容又有些许不同,let 和 const 这两个新关键字对提升的表现也和 var 不同,具体可以参阅 ES6 中的相关内容。

现在和提升相关的内容更多的出现在面试题里,由于代码检查工具的介入,一些由于提升特性造成的 BUG 出现的越来越少。

前置知识
什么是JavaScript 开发与学习环境准备 调试方案
基础
JavaScript 变量 JavaScript 数据类型 JavaScript if 语句 JavaScript for 语句 JavaScript 算数运算符 JavaScript 比较运算符 JavaScript 逻辑运算符 JavaScript 表达式 JavaScript 函数 JavaScript 对象 JavaScript 字符串 JavaScript 数字 JavaScript 数组 JavaScript switch 语句 JavaScript while 语句 JavaScript break与continue JavaScript with document.cookie
内置对象
JavaScript Function JavaScript Math JavaScript Date JavaScript RegExp JavaScript JSON
JavaScript 与 DOM
什么是DOM DOM和JavaScript的关系 获取和操作 DOM 节点 JavaScript DOM与事件 JavaScript DOM 事件绑定 JavaScript DOM 事件对象 JavaScript DOM 事件流 JavaScript DOM 事件优化 JavaScript DOM 自定义事件
表单处理
使用 JavaScript 校验表单
BOM
BOM window 对象 常用的 BOM 相关对象 BOM 常用属性和方法
AJAX
JavaScript AJAX
进阶知识
JavaScript 异常处理 JavaScript 三元运算符 JavaScript 逗号操作符 JavaScript void JavaScript typeof JavaScript delete JavaScript debugger JavaScript getter &setter JavaScript 原型 JavaScript new操作符和构造函数 JavaScript instanceof JavaScript this JavaScript 严格模式 JavaScript 作用域 JavaScript 闭包 JavaScript 变量提升 JavaScript 对象包装器
常用库
jQuery Lodash moment.js swiper
进阶指南
ECMAScript6 Node.js Babel CSS 预处理器 代码规范 TypeScript Web Components 小程序 Vue / React / Angular JavaScript 关键字
常见疑点与误区
分号问题 对象属性访问问题 this 使用问题 浮点数精度问题 独一无二的 NaN 避免全局污染 控制台观察对象问题 根据环境选择语言特性
扩展
相关资源