【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>

执行结果 :

相关推荐
Auc24几秒前
使用scrapy框架爬取微博热搜榜
开发语言·python
QQ同步助手7 分钟前
C++ 指针进阶:动态内存与复杂应用
开发语言·c++
程序员海军10 分钟前
2024 Nuxt3 年度生态总结
前端·nuxt.js
凯子坚持 c13 分钟前
仓颉编程语言深入教程:基础概念和数据类型
开发语言·华为
小爬虫程序猿15 分钟前
利用Java爬虫速卖通按关键字搜索AliExpress商品
java·开发语言·爬虫
程序猿-瑞瑞17 分钟前
24 go语言(golang) - gorm框架安装及使用案例详解
开发语言·后端·golang·gorm
qq_4335545418 分钟前
C++ 面向对象编程:递增重载
开发语言·c++·算法
m0_7482567820 分钟前
SpringBoot 依赖之Spring Web
前端·spring boot·spring
易码智能26 分钟前
【EtherCATBasics】- KRTS C++示例精讲(2)
开发语言·c++·kithara·windows 实时套件·krts
一只自律的鸡27 分钟前
C语言项目 天天酷跑(上篇)
c语言·开发语言