【JavaScript】预解析 ① ( 变量预解析 - 变量提升 | 函数预解析 - 函数提升 | 函数表达式预解析 )

文章目录

  • [一、JavaScript 预解析](#一、JavaScript 预解析)
  • 二、变量预解析
    • [1、变量预解析 - 变量提升](#1、变量预解析 - 变量提升)
    • [2、代码示例 - 变量预解析](#2、代码示例 - 变量预解析)
  • 三、函数预解析
    • [1、函数预解析 - 函数提升](#1、函数预解析 - 函数提升)
    • [2、代码示例 - 函数预解析](#2、代码示例 - 函数预解析)
  • 四、函数表达式预解析

一、JavaScript 预解析


JavaScript 代码 是 由 浏览器 的 JavaScript 解析器 执行的 , 执行过程分如下两步 :

  • 预解析
  • 正式执行代码

JavaScript 的 " 预解析 " 又称为 " 变量和函数的提升 " , 会把 var 变量声明 和 function 函数声明 提升到 当前作用域 的 最前面 ;

预解析 机制 允许在代码中 , 无论实际 声明变量 / 声明函数 的位置在哪里 , 解析器 在 预解析 阶段 都会把它们提升到它们各 自的作用域的最顶部 ;

二、变量预解析


1、变量预解析 - 变量提升

变量预解析 又称为 " 变量提升 " , 就是 把 所有的 变量声明 , 提升到 当前 作用域 的 最前面 ;

在 JavaScript 中 , 使用 var 关键字声明的变量 , 会被提升到其所在的 全局作用域 或 局部作用域 的顶部 ;

注意 : 只有 变量 的声明 会被提升 , 初始化操作 不会被提升 , 如果 在声明之前尝试访问一个变量 , 只能访问到 未初始化 的变量值 undefined ;

以下面的代码为例 :

cpp 复制代码
// 输出 undefined , 只有变量声明被提升 , 变量初始化在后面
console.log(num); 
// 声明变量 , 并将变量初始化为 5 
var num = 5;

var num = 5; 操作其实是两步操作 , 先声明了变量 , 在为变量初始化了数值 5 ;

cpp 复制代码
var num;
num = 5;

变量提升 , 只将 变量声明 , 也就是 var num; 语句提升到了 当前作用域 的最前面 , num = 5; 初始化赋值操作 仍然在原来的位置 ;

预解析 变量提升 的效果相当于将 代码转为 :

cpp 复制代码
// 声明变量
var num;
// 输出 undefined , 只有变量声明被提升 , 变量初始化在后面
console.log(num); 
// 变量初始化赋值 5 
num = 5;

2、代码示例 - 变量预解析

下面的代码中的 JavaScript 代码 , 最终执行结果与下面的代码一致 ;

JavaScript 引擎 将

js 复制代码
// 输出 undefined , 只有变量声明被提升 , 变量初始化在后面
console.log(num); 
// 声明变量 , 并将变量初始化为 5 
var num = 5;

预解析为 :

js 复制代码
// 声明变量
var num;
// 输出 undefined , 只有变量声明被提升 , 变量初始化在后面
console.log(num); 
// 变量初始化赋值 5 
num = 5;

代码示例 :

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <!-- 设置 meta 视口标签 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no,maximum-scale=1.0,minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>JavaScript</title>
    <style></style>
    <script>
        // 预解析

        // 变量预解析 - 变量提升
        // 输出 undefined , 只有变量声明被提升 , 变量初始化在后面
        console.log(num);
        // 声明变量 , 并将变量初始化为 5 
        var num = 5;
    </script>
</head>

<body>
</body>

</html>

执行结果 :

三、函数预解析


1、函数预解析 - 函数提升

函数预解析 又称为 " 函数提升 " , 与 变量提升类似 , 使用 function 关键字 的 函数声明 也会被提升到它们所在的作用域的顶部 , 因此可以 在函数声明之前 调用该函数 ;

在下面的代码中 , 先调用了 hello 函数 , 再使用 function 关键字 声明函数 ,

js 复制代码
        hello();

        function hello() {
            console.log("Hello");
        }

在 JavaScript 引擎 进行 预解析时 , 函数预解析 就是将 function 关键字声明的函数 , 提升到 作用域最顶端 , 因此 可以在 函数执行前调用 该函数 ;

函数预解析 后的 代码效果如下 , 调用 hello 函数 , 成功执行该函数 , 这是因为 函数预解析 过程将 函数提升到了 作用域最顶端 ;

js 复制代码
		function hello() {
            console.log("Hello");
        }
        hello();

2、代码示例 - 函数预解析

代码示例 :

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <!-- 设置 meta 视口标签 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no,maximum-scale=1.0,minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>JavaScript</title>
    <style></style>
    <script>
        // 预解析

        // 函数预解析 - 函数提升

        // 输出 Hello , 函数声明提升到 作用域最顶部
        hello();

        // 函数预解析
        function hello() {
            console.log("Hello");
        }
    </script>
</head>

<body>
</body>

</html>

执行结果 :

四、函数表达式预解析


1、函数表达式预解析

函数表达式 的 本质是一个 变量 , 只是将 函数 赋值给了 变量 ;

由于 变量预解析 时 , 只是将 var 关键字的 变量声明 提升到了 作用域的最顶端 , 变量的 初始化 仍然在原地 ;

此时 通过该 变量 调用函数 , 肯定会报错 , 因为 函数此时没有赋值给 该变量 ;

在下面的代码中 , var fun 是一个变量 , 因此这里只进行 变量的提升 ,

js 复制代码
        // 报错 : Uncaught TypeError: fun is not a function
        fun();

        // 函数预解析
        var fun = function hello() {
            console.log("Hello");
        }

变量提升后的效果如下 :

js 复制代码
		// 函数提升
		var fun;
		
        // 报错 : Uncaught TypeError: fun is not a function
        fun();

        // 将 函数表达式 赋值给 fun 变量
        fun = function hello() {
            console.log("Hello");
        }

上述代码执行后 , 就会报错 Uncaught TypeError: fun is not a function ;

2、代码示例 - 函数表达式预解析

代码示例 :

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <!-- 设置 meta 视口标签 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no,maximum-scale=1.0,minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>JavaScript</title>
    <style></style>
    <script>
        // 预解析

        // 函数表达式 预解析情况

        // 报错 : Uncaught TypeError: fun is not a function
        fun();

        // 函数预解析
        var fun = function hello() {
            console.log("Hello");
        }
    </script>
</head>

<body>
</body>

</html>

执行结果 :

相关推荐
小镇程序员1 分钟前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐3 分钟前
前端图像处理(一)
前端
tangliang_cn10 分钟前
java入门 自定义springboot starter
java·开发语言·spring boot
程序猿阿伟10 分钟前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
疯狂的沙粒12 分钟前
对 TypeScript 中函数如何更好的理解及使用?与 JavaScript 函数有哪些区别?
前端·javascript·typescript
瑞雨溪21 分钟前
AJAX的基本使用
前端·javascript·ajax
新知图书21 分钟前
Rust编程与项目实战-模块std::thread(之一)
开发语言·后端·rust
威威猫的栗子23 分钟前
Python Turtle召唤童年:喜羊羊与灰太狼之懒羊羊绘画
开发语言·python
力透键背23 分钟前
display: none和visibility: hidden的区别
开发语言·前端·javascript
bluefox197924 分钟前
使用 Oracle.DataAccess.Client 驱动 和 OleDB 调用Oracle 函数的区别
开发语言·c#