JS预解析/编译(变量提升):var(仅声明,无赋值)、function变量 创建作用域

news2025/1/12 3:53:39

目录

变量提升/预定义

function和var

重名:函数覆盖变量

不执行代码

重复声明:只提升一次

函数形参:变量提升

带 var 和不带 var 

全局作用域: window 的属性

私有/函数作用域:

带 var 的是私有变量

IIFE 函数具备自己的作用域,所以全局下不会变量提升

匿名自执行函数在自己的作用域内存在正常的变量提升

非匿名自执行函数的函数名在自己的作用域内变量提升,且修改函数名的值无效

不带 var 的是会沿着作用域链查找

var a=b=1  等价于var a=1;b=1

let、const 、class的暂时性死区

顶级作用域和函数作用域:let 不会在全局对象上创建属性

let不允许重复声明

*编译

分词/词法分析:分解(var a=2=> var,a,=,2)

解析/语法分析:词法数组=>程序语法 结构的“抽象语法树”(a->2)(Abstract Syntax Tree,AST)

代码生成:将 AST 转换为可执行代码


变量提升/预定义

变量提升是当栈内存作用域形成时,JS执行前,浏览器会将带有var, function关键字的变量提前进行声明 declare(值默认就是 undefined),定义 defined(就是赋值操作),这种预先处理的机制就叫做变量提升机制也叫预定义。

 JS 运行机制基础版

function和var

print()
function print(){
    console.log('林一一')
}
print()

print()
var print = function() {
    console.log('林一一')
}
print()
/*输出
    Uncaught TypeError: print is not a function
/

重名:函数覆盖变量

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

// 或

console.log(a);   
function a(){
    console.log(1);
}
var a=1;
// 输出都是: ƒ a(){ console.log(1);}

不执行代码

​
console.log(a)
if(false){
    var a = '林一一'
}
console.log(a)
/* 输出
    undefined
    undefined
/


​

重复声明:只提升一次

var a = 1;
function foo(a) {
    console.log(a)
    var a
    console.log(a)
}
foo(a);
// 输出 1 1

函数形参:变量提升

function a(b){
  console.log(b);  
}
a(45);

// 等价于
// function a(b) {
//     var b = undefined;
//     b = 45;
// }

带 var 和不带 var 

全局作用域: window 的属性

私有/函数作用域:

var 的是私有变量
IIFE 函数具备自己的作用域,所以全局下不会变量提升
var a = 10;
(function c(){
})()
console.log(c)
// Uncaught ReferenceError: c is not defined
匿名自执行函数在自己的作用域内存在正常的变量提升
var a = 10;
(function(){
    console.log(a)
    a = 20
    console.log(a)
})()
console.log(a)
// 10, 20, 20
非匿名自执行函数的函数名在自己的作用域内变量提升,且修改函数名的值无效
var a = 10;
(function a(){
    console.log(a)
    a = 20
    console.log(a)
})()
// ƒ a(){a = 20 console.log(a)}  ƒ a(){a = 20 console.log(a)}
var foo = '林一一';
(function(f){
    console.log(foo);
})(foo);
// undefined


var foo = '林一一';
(function(f){
    console.log(foo);
    var foo = f || 'hello';
})(foo);
//undefined
var a = 10;
console.log(window.a);
(function () {
    console.log(a)
    a = 5
    console.log(window.a)
    var a = 20;
    console.log(a)
})()
//undefined undefined undefined 20 
不带 var 的是会沿着作用域链查找
function foo(){
    console.log(a)
    a =12;
    b = '林一一'
    console.log('b' in window)
    console.log(a, b)
}
foo()
/* 输出
    Uncaught ReferenceError: a is not defined
/

var a=b=1  等价于var a=1;b=1

// 1
console.log(a, b)
var a =12, b ='林一一'
function foo(){
// 2
    console.log(a, b)
// 3
    var a = b =13
    console.log(a, b)
}
foo()
console.log(a, b)

/* 输出:
    undefined undefined
    undefined "林一一"
    13 13
    12 13
*/

1处的 a, b 其实就是 window下面的属性为 undefined。在函数内部由于变量提升机制 avar 一开始就是 undefined,b不带var 将向上级作用域查找,找到全局作用域下的林一一所以2处打印出来的就是 undefined "林一一"。随后 a =13,window.b =13,即原来 b='林一一' 变成了 b=13,打印出13, 13,最后第4处打印处12, 13

letconst 、class的暂时性死区

“暂时性”区:这个区域取决于代码执行的时间点,而不是代码编写的顺序。

{
  // 暂时性死区始于作用域开头
  const func = () => console.log(letVar); // 没问题

  // 在暂时性死区内访问 letVar 会抛出 `ReferenceError`

  let letVar = 3; // 暂时性死区结束(对 letVar 而言)
  func(); // 在暂时性死区外调用
}

用 letconst 或 class 声明的变量可以称其从代码块的开始一直到代码执行到变量声明的位置并被初始化前,都处于一个“暂时性死区”(Temporal dead zone,TDZ)中。

当变量处于暂时性死区之中时,其尚未被初始化,并且任何访问其的尝试都将导致抛出 ReferenceError。

当代码执行到变量被声明的位置时,变量会被初始化为一个值。如果变量声明中未指定初始值,则变量将被初始化为 undefined

这与 var 声明的变量不同,如果在声明位置前访问 var 声明的变量会返回 undefined

{
  // 暂时性死区始于作用域开头
  console.log(bar); // undefined
  console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
  var bar = 1;
  let foo = 2; // 暂时性死区结束(对 foo 而言)
}

顶级作用域和函数作用域:let 不会在全局对象上创建属性

var x = "global";
let y = "global";
console.log(this.x); // "global"
console.log(this.y); // undefined

let不允许重复声明

let x = 1;

{
  var x = 2; // 重复声明的 SyntaxError
}

参考链接:彻底解决 JS 变量提升| 一题一图,超详细包教包会😉 - 掘金

*编译

分词/词法分析:分解(var a=2=> var,a,=,2)

解析/语法分析:词法数组=>程序语法 结构的“抽象语法树”(a->2)(Abstract Syntax Tree,AST)

代码生成:将 AST 转换为可执行代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1037314.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux 终端与进程

有趣的问题 Linux 中的 终端,控制台,TTY,PTY 究竟是什么?它们与进程有什么关系? 历史回顾:控制台 (Console) 控制台是一个直接控制设备的面板 (属于设备的一部分) 计算机设备的控制台:按键 &…

2FSK调制解调VHDL,Quartus

名称:2FSK调制解调VHDL(代码在文末付费下载) 软件:Quartus 语言:VHDL 要求:使用VHDL实现2FSK的调制和解调,并进行仿真 代码下载:2FSK调制解调VHDL,Quartus_Verilog/VHDL资源下载…

C++ stack queue模拟实现

目录 一.stack 二.queue 三.deque STL中有6大组件,我们前面讲的string/vector/list是容器,还有迭代器,以及算法(比如find,swap,reverse,sort,merge函数),仿函…

【Java 基础篇】Java Stream 流详解

Java Stream(流)是Java 8引入的一个强大的新特性,用于处理集合数据。它提供了一种更简洁、更灵活的方式来操作数据,可以大大提高代码的可读性和可维护性。本文将详细介绍Java Stream流的概念、用法和一些常见操作。 什么是Stream…

bootstrapv4轮播图去除两侧阴影及线框的方法

文章目录 前言一、前提条件:二、bootstrap文档组件展示与实际应用1.官方文档展示如下:没有阴影2.实际应用情况如下: 三、解决方案 前言 这篇文章主要介绍了bootstrapv4轮播图去除两侧阴影及线框的方法,本文通过示例代码给大家介绍的非常详细…

基于微信小程序的项目申报管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言用户微信端的主要功能有:管理员的主要功能有:具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding)有保障的售后福利 代码参考源码获取 前言 💗博主介绍:✌全网粉…

【Vue】vue-cli一站式搭建SPA项目

🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚 🌟推荐给大家我的专栏《Vue快速入门》。🎯🎯 &…

vtk- 数据类型(一) 三角链实例代码

三角链实例代码 #include <iostream> #include <string> #include <regex> #include "tuex.h" #include "vtkCylinderSource.h" #include "vtkPolyDataMapper.h" #include "vtkActor.h" #include "vtkRendere…

Java --- MySQL8数据库优化性能查看工具

目录 一、数据库服务器优化步骤 ​编辑二、查看系统性能的参数 三、统计SQL的查询成本&#xff1a;last_query_cost 四、定位执行慢的SQL&#xff1a;慢日志查询 4.1、开启并设置慢查询日志查询参数 4.2、查看慢查询数目 4.3、慢查询日志分析工具&#xff1a;mysqldumps…

MySQL单表查询和多表查询

一、单表查询 素材&#xff1a; 表名&#xff1a;worker-- 表中字段均为中文&#xff0c;比如 部门号 工资 职工号 参加工作等 CREATE TABLE worker (部门号 int(11) NOT NULL,职工号 int(11) NOT NULL,工作时间 date NOT NULL,工资 float(8,2) NOT NULL,政治面貌 varchar(10)…

帆软FineReport决策报表之页面布局

最近在用帆软决策报表绘制首页大屏&#xff0c;记录使用过程&#xff0c;方便查看。 版本&#xff1a;FineReport10.0 第一步、页面布局 页面布局其实就是组件的排列组合&#xff0c;决策报表主区域body有两种布局方式&#xff1a;自适应布局和绝对布局。 1&#xff09;自适应…

C#中实现单元测试的示例流程_MSTest测试项目

一、单元测试简介 1.1、单元测试简介 在《单元测试艺术》一书中对于单元测试的定义是&#xff1a;【一个单元测试是一段代码&#xff0c;这段代码调用一个工作单元&#xff08;指&#xff1a;调用软件中的一个方法&#xff0c;这个方法执行过程中所发生的所有行为以及最后产生…

你好,python!——python基础中的基础

〇、注释 0.1 单行注释 python中用 “# ”来给某一行注释&#xff0c; 他的快捷键是 CTRL / &#xff0c;当注释内容已被注释时&#xff0c;会解除注释 0.2 多行注释 python中用 """ 注释内容 """ 来对内容进行多行注释 ""&q…

DATE和LocalDateTime在Java中有什么区别

在Java中&#xff0c;Date和LocalDateTime是两个表示日期和时间的类&#xff0c;它们有以下区别&#xff1a; 类型&#xff1a;Date是Java旧版提供的日期和时间类&#xff0c;而LocalDateTime是Java 8引入的新日期和时间API中的类。 不可变性&#xff1a;Date是可变类&#x…

Questasim与Visualizer的livesim仿真

1.前言 Live-Simulation (live-sim)模式允许Visualizer调试环境与Questasim进行交互操作&#xff0c;此模式将Visualizer GUI与Questasim仿真相结合&#xff0c;因此可以在线调试当前仿真的结果和波形。在livesim模式中&#xff0c;可以在Visualizer GUI中控制仿真、设置断点(…

【Java 基础篇】Java 类加载器详解

在Java编程中&#xff0c;类加载器&#xff08;Class Loader&#xff09;是一个重要的概念&#xff0c;它负责将类加载到Java虚拟机中&#xff0c;使程序能够正常运行。本文将详细解释Java类加载器的工作原理、不同类型的类加载器以及如何自定义类加载器。 什么是类加载器&…

智慧公厕以数字技术为中心,融合数字管理技术与城市治理需求精准对接

现代城市的发展离不开科技的进步&#xff0c;智慧公厕作为城市治理的重要方面之一&#xff0c;正逐渐受到越来越多的重视。智慧公厕以数字技术为中心&#xff0c;融合数字管理技术与城市治理需求精准对接&#xff0c;为城市居民提供更加方便、舒适的公共卫生设施。本文将以智慧…

2023年7月嵌入式项目开发专题总汇

一、前言 当前文章总结了28个基于不同单片机&#xff08;51单片机和STM32&#xff09;设计的软件和硬件项目。这些项目涵盖了计算器、手机、酒精检测仪、环境温度与湿度检测设备、考勤系统、门禁照相机、人体健康检测仪、数码相册、太阳能热水器、数显热水器和智能空调等多个领…

高性能计算环境下的深度学习异构集群建设与优化实践

★深度学习&#xff1b;模式识别&#xff1b;图像处理&#xff1b;人工智能建模&#xff1b;人工智能&#xff1b;深度学习算法&#xff1b;强化学习&#xff1b;神经网络&#xff1b;卷积神经网络&#xff1b;人工神经网络&#xff1b;VIBE算法&#xff1b;控制系统仿真&#…

用Redis做数据排名

1.背景 用Redis做数据缓存用的比较多&#xff0c;大家都能熟练使用String和Hash结构去存储数据&#xff0c;今天讲下如何使用ZSet来做数据排名。 假设场景是需要按天存储全国城市的得分数据&#xff0c;可以查询前十名的城市排名。 这个case可以使用传统关系型数据库做…