【深入理解ES6】块级作用域绑定

1. var声明及变量提升机制

提升(Hoisting)机制:通过关键字var声明的变量,都会被当成在当前作用域顶部生命的变量。

function getValue(condition){if(condition){var value = "blue";console.log(value);}else{// 此处可访问变量value,其值为undefinedreturn null}// 此处可访问变量value,其值为undefined
}

JavaScript引擎会将上面的getValue函数修改为下面这样。变量value的声明被提升至函数顶部,初始化操作依旧保留在原处执行。为此,ES6引入了块级作用域来强化对变量声明周期的控制。

function getValue(condition){var value;if(condition){value = "blue";console.log(value);}else{return null}
}

 

2. 块级声明

块级声明用于声明在指定块的作用域之外无法访问的变量。

块级作用域存在于:

  • 函数内部
  • 块中(‘{}’之间的区域)。

2.1. let声明

  • 用法同var相同,但声明不会被提升;
  • 禁止在同一作用域内重声明;
  • 如果当前作用域内嵌另一个作用域,便可在内嵌的作用域中用let声明同名变量。
function getValue(condition){if(condition){var value = "blue";console.log(value);}else{// 变量value在此处不存在return null}// 变量value在此处不存在
}
/**禁止重声明*/var count = 30;
// 抛出语法错误
let count = 40;if(condition){// 不会抛出错误let count = 40;
}

2.2. const声明

  • 声明的是常量,必须初始化;
  • 禁止在同一作用域内重声明;
  • 不可再赋值(常量对象可修改值;
  • const声明对象时,不允许修改绑定,但可修改值。
// 有效的常量
const maxItems = 30;
// 语法错误,未初始化
const name;if(condition){const cnt = 40;
}
// 在此处无法访问cntlet age = 20;
// 抛出错误,重声明
const age = 15;const pos = 30;
// 抛出语法错误,不能重新赋值
pos = 35;const person = {name: 'Nicholas'
};
// 可以直接修改对象属性的值
person.name = 'Fleur';
// 直接给person赋值,即要改变person的绑定,会抛出语法错误。
person = {name: 'DpprZ'
}

 

3. 临时死区(Temppral Dead Zone, TDZ) 

由于 console.log(typeof value) 语句会抛出错误,因此用 let 定义并初始化变量 value 的语句不会执行。此时的 value 还位于 JavaScript 社区所谓的“临时死区”。TDZ 通常用来描述 let 和 const 的不提升效果。

if(condition){console.log(typeof value);  // 引用错误let value = 40;
}
console.log(typeof value);  // "undefined"
if(condition){let value = 40;
}

 JS引擎扫描代码发现变量声明时:

  • var声明:将他们提升至作用域顶部。
  • let和const声明:将声明放在TDZ中。访问TDZ中的变量会触发运行时错误。只有执行过变睾声明语句后,变量才会从TDZ中移除,然后方可正常访问。

 

4. 循环中的块级作用域绑定

for循环中通过let将计数器变量限制在循环内部。

for(var i = 0; i < 10; i++){// 更多代码
}
// 在这里仍然可以访问变量i
console.log(i); // 10for(let i = 0; i < 10; i++){// 更多代码
}
// i在这里不可访问,抛出错误
console.log(i); 

 

5. 循环中的函数、let声明、const声明

let funcs = [];
for(var i = 0; i < 10; i++){funcs.push(function(){console.log(i)})
}
/*
每个funcs[]中都存在一个函数:ƒ (){ console.log(i) }
*/
funcs.forEach(function(func){func(); // 10个10
})

因为这里的循环里的每次迭代同时共享着变量i,循环内部创建的函数都保留了对相同变量的引用。
解决该问题的两种方案:

在循环中使用立即调用函数表达式(IIFE),以强制生成计数器变量的副本。

let funcs = [];for(var i = 0; i < 10; i++){funcs.push(function(value){return function(){console.log(value)}})
}funcs.forEach(function(func){func(); // 0 1 2 3......9
})

用let声明计数器:每次迭代循环都会创建一个新变量 i,并以之前迭代同名变量的值将其初始化。所以循环内部创建的每一个函数都能够得到属于自己的 i 的值。let 声明在循环内部的行为是标准中专门定义的,它不一定与let的不提升特性相关,理解这一点至关重要!

let funcs = [];for(let i = 0; i < 10; i++){funcs.push(function(){console.log(i)})
}funcs.forEach(function(func){func(); // 0 1 2 3...... 9
})
  •  let声明:声明计数器、for-in、for-of
  • const声明:生命循环内不改变的值、for-in、for-of

 

6. 全局块作用域绑定

var、let、const在全局作用域中的行为区别:

var会创建一个新的变量作为全局对象(浏览器环境中的window对象),会无意中覆盖已存在的全局属性。

let、const会在全局作用域下创建一个新的绑定,但该绑定不会添加为全局对象的属性。换句话说,不能覆盖只是遮蔽。 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是网络地址转换 (NAT)

网络地址转换&#xff08;NAT&#xff09;是更改源和目标 IP 地址和端口的过程&#xff0c;地址转换减少了对 IPv4 公共地址的需求&#xff0c;并隐藏了专用网络地址范围&#xff0c;该过程通常由路由器或防火墙完成。 NAT是如何工作的 NAT 允许单个设备&#xff08;如路由器…

汽车级36V、4A同步降压转换器MAX20404AFOD/VY、MAX20404AFOC/VY、MAX20404AFOA/VY开关稳压器

MAX20404是小型同步降压转换器&#xff0c;集成了高端和低端开关。这些IC均设计为可在3V到36V的宽输入电压范围内提供高达4A的电流。电压质量可以通过观察PGOOD信号来监测。该器件可以在99%的占空比下运行&#xff0c;非常适合汽车和工业应用。 MAX20404提供可编程输出电压或5…

探索高级UI、源码解析与性能优化,了解开源框架及Flutter,助力Java和Kotlin筑基,揭秘NDK的魅力!

课程链接&#xff1a; 链接: https://pan.baidu.com/s/13cR0Ip6lzgFoz0rcmgYGZA?pwdy7hp 提取码: y7hp 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 --来自百度网盘超级会员v4的分享 课程介绍&#xff1a; &#x1f4da;【01】Java筑基&#xff1a;全方位指…

Spring Boot业务代码中使用@Transactional事务失效踩坑点总结

1.概述 接着之前我们对Spring AOP以及基于AOP实现事务控制的上文&#xff0c;今天我们来看看平时在项目业务开发中使用声明式事务Transactional的失效场景&#xff0c;并分析其失效原因&#xff0c;从而帮助开发人员尽量避免踩坑。 我们知道 Spring 声明式事务功能提供了极其…

年至年的选择仿elementui的样式

组件&#xff1a;<!--* Author: liuyu liuyuxizhengtech.com* Date: 2023-02-01 16:57:27* LastEditors: wangping wangpingxizhengtech.com* LastEditTime: 2023-06-30 17:25:14* Description: 时间选择年 - 年 --> <template><div class"yearPicker"…

更多openEuler镜像加入AWS Marketplace!

自2023年7月openEuler 22.03 LTS SP1正式登陆AWS Marketplace后&#xff0c;openEuler社区一直持续于在AWS上提供更多版本。 目前&#xff0c;openEuler22.03 LTS SP1 ,SP2两个版本及 x86 arm64两种架构的四个镜像均可通过AWS对外提供&#xff0c;且在亚太及欧洲15个Region开放…

【HCIP】BGP总结

一、bgp介绍 1.概念 边界网关协议BGP&#xff08;Border Gateway Protocol&#xff09;是一种实现自治系统AS之间的路由可达&#xff0c;并选择最佳路由的路径矢量路由协议。目前在IPV4环境下主要使用BGPV4&#xff0c;目前市场上也存BGPV4&#xff0c;BGPV4在BGPV4的基础上支…

.net连接mysql,提示找不到请求的 .Net Framework Data Provider。可能没有安装

开发完成的.net程序需要连接mysql数据库&#xff0c;在个人电脑上运行没问题&#xff0c;别人运行时提示“提示找不到请求的 .Net Framework Data Provider。可能没有安装”。经过查询&#xff0c;安装Connector/NET 8.1.0&#xff0c;下载地址如下所示&#xff1a; https://d…

攻击LNMP架构Web应用

环境配置(centos7) 1.php56 php56-fpm //配置epel yum install epel-release rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm//安装php56&#xff0c;php56-fpm及其依赖 yum --enablereporemi install php56-php yum --enablereporemi install php…

SpringBoot的配置文件(properties与yml)

文章目录 1. 配置文件的作用2. 配置文件格式3. 配置文件的使用方法3.1. properties配置文件3.1.1. 基本语法和使用3.1.2. properties优缺点分析 3.2. yml配置文件3.2.1. 基本语法与使用3.2.2. yml中单双引号问题3.2.3. yml配置不同类型的数据类型及null3.2.4. 配置对象3.2.5. 配…

【计算机网络】13、ARP 包:广播自己的 mac 地址和 ip

机器启动时&#xff0c;会向外广播自己的 mac 地址和 ip 地址&#xff0c;这个即称为 arp 协议。范围是未经过路由器的部分&#xff0c;如下图的蓝色部分&#xff0c;范围内的设备都会在本地记录 mac 和 ip 的绑定信息&#xff0c;若有重复则覆盖更新&#xff08;例如先收到 ma…

ATF(TF-A)安全通告 TFV-5 (CVE-2017-15031)

安全之安全(security)博客目录导读 ATF(TF-A)安全通告汇总 目录 一、ATF(TF-A)安全通告 TFV-5 (CVE-2017-15031) 二、CVE-2017-15031 一、ATF(TF-A)安全通告 TFV-5 (CVE-2017-15031) Title 未初始化或保存/恢复PMCR_EL0可能会泄露安全世界的时间信息 CVE ID CVE-2017-1503…