【深入理解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.mzph.cn/news/40920.shtml

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

相关文章

代码随想录算法训练营第三十六天 | 435. 无重叠区间,763.划分字母区间,56. 合并区间

代码随想录算法训练营第三十六天 | 435. 无重叠区间&#xff0c;763.划分字母区间&#xff0c;56. 合并区间 435. 无重叠区间:eyes:题目总结:eyes: 763.划分字母区间:eyes:题目总结:eyes: 56. 合并区间:eyes:题目总结:eyes: 435. 无重叠区间 题目链接 视频讲解 给定一个区间的…

并发编程系列-Semaphore

Semaphore&#xff0c;如今通常被翻译为"信号量"&#xff0c;过去也曾被翻译为"信号灯"&#xff0c;因为类似于现实生活中的红绿灯&#xff0c;车辆是否能通行取决于是否是绿灯。同样&#xff0c;在编程世界中&#xff0c;线程是否能执行取决于信号量是否允…

8.10 用redis实现缓存功能和Spring Cache

什么是缓存? 缓存(Cache), 就是数据交换的缓冲区,俗称的缓存就是缓冲区内的数据,一般从数据库中获取,存储于本地代码。 通过Redis来缓存数据&#xff0c;减少数据库查询操作; 逻辑 每个分类的菜品保存一份缓存数据 数据库菜品数据有变更时清理缓存数据 如何将商品数据缓存起…

p-级数的上界(Upper bound of p-series)

积分判别法-The Integral Test https://math.stackexchange.com/questions/2858067/upper-bound-of-p-series https://courses.lumenlearning.com/calculus2/chapter/the-p-series-and-estimating-series-value/ 两个重要级数&#xff08;p级数和几何级数&#xff09; ht…

WPF显示初始界面--SplashScreen

WPF显示初始界面–SplashScreen 前言 WPF应用程序的运行速度快&#xff0c;但并不能在瞬间启动。当第一次启动应用程序时&#xff0c;会有一些延迟&#xff0c;因为公共语言运行时&#xff08;CLR&#xff09;首先需要初始化.NET环境&#xff0c;然后启动应用程序。 对于WPF中…

高忆管理:股票T+0交易是什么意思?t+0交易有什么好处?

股票的买卖准则有很多种&#xff0c;T0买卖便是其中之一。那么股票T0买卖是什么意思&#xff1f;t0买卖有什么优点&#xff1f;高忆管理也为大家预备了相关内容&#xff0c;以供参考。 股票T0买卖是什么意思&#xff1f; T0买卖准则是指出资者当天买入的股票能够在当天卖出&am…

IP 多播协议(IP Multicast Protocol)

IP 多播协议&#xff08;IP Multicast Protocol&#xff09;是一种在网络中一对多传输数据的通信方式。在传统的单播通信中&#xff0c;数据从一个发送方发送到一个接收方&#xff1b;而在多播通信中&#xff0c;数据可以从一个发送方传输到多个接收方&#xff0c;从而有效地节…

SpringBoot 异步、邮件任务

异步任务 创建一个Hello项目 创建一个类AsyncService 异步处理还是非常常用的&#xff0c;比如我们在网站上发送邮件&#xff0c;后台会去发送邮件&#xff0c;此时前台会造成响应不动&#xff0c;直到邮件发送完毕&#xff0c;响应才会成功&#xff0c;所以我们一般会采用多线…

神经网络基础-神经网络补充概念-03-逻辑回归损失函数

概念 逻辑回归使用的损失函数通常是"对数损失"&#xff08;也称为"交叉熵损失"&#xff09;或"逻辑损失"。这些损失函数在训练过程中用于衡量模型预测与实际标签之间的差异&#xff0c;从而帮助模型逐步调整权重参数&#xff0c;以更好地拟合数…

指静脉开集测试(OpenSet-test)代码(包含7个数据集)

七个数据集:sdu、mmc、hkpu、scut、utfvp、vera、nupt 一、SDU 80%用于训练,20%用于作为开集测试 1.数据集分割代码 ①先把636个类别提取出来 func: 创建temp_sdu,将636个类划分出来。下一个代码块将进行openset_sdu的分割import os from shutil import copy, rmtre…

c++--SLT六大组件之间的关系

1.SLT六大组件&#xff1a; 容器&#xff0c;迭代器&#xff0c;算法&#xff0c;仿函数&#xff0c;适配器&#xff0c;空间配置器 2.六大组件之间的关系 容器&#xff1a;容器是STL最基础的组件&#xff0c;没有容器&#xff0c;就没有数据&#xff0c;容器的作用就是用来存…

IO流 详细介绍

一、IO流概述 1.IO&#xff1a;输入(Input读取数据)/输出(Output写数据) 2.流&#xff1a;是一种抽象概念&#xff0c;是对数据传输的总称,也就是说数据在设备间的传输称为流&#xff0c;流的本质是数据传输IO流就是用来处理设备间数据传输问题的。 3.常见的应用&#xff1a…

【Sklearn】基于随机森林算法的数据分类预测(Excel可直接替换数据)

【Sklearn】基于随机森林算法的数据分类预测(Excel可直接替换数据) 1.模型原理1.1 模型原理1.2 数学模型2.模型参数3.文件结构4.Excel数据5.下载地址6.完整代码7.运行结果1.模型原理 随机森林(Random Forest)是一种集成学习方法,通过组合多个决策树来构建强大的分类或回归…

JVM - 垃圾回收机制

JVM的垃圾回收机制(简称GC) JVM的垃圾回收机制非常强大&#xff0c;是JVM的一个很重要的功能&#xff0c;而且这也是跟对象实例息息相关的&#xff0c;如果对象实例不用了要怎么清除呢&#xff1f; 如何判断对象已经没用了 当JVM认为一个对像已经没用了&#xff0c;就会把这个…

初识Sentinel

目录 1.解决雪崩的方式有4种&#xff1a; 1.1.2超时处理&#xff1a; 1.1.3仓壁模式 1.1.4.断路器 1.1.5.限流 1.1.6.总结 1.2.服务保护技术对比 1.3.Sentinel介绍和安装 1.3.1.初识Sentinel 1.3.2.安装Sentinel 1.4.微服务整合Sentinel 2.流量控制 2.1.簇点链路 …

Ubuntu中怎么清空mysql数据

要清空 MySQL 数据&#xff0c;可以使用以下步骤来执行。请注意&#xff0c;这将会永久删除数据库中的所有数据&#xff0c;请谨慎操作&#xff0c;并在操作前备份重要数据。 登录 MySQL&#xff1a; 打开终端&#xff0c;使用以下命令登录到 MySQL 数据库。根据情况&#xf…

黑马项目一阶段面试58题 Web14题(一)

一、什么是AJAX 异步的JavaScript和XML。用来做前端和后端的异步请求的技术。 异步请求&#xff1a;只更新部分前端界面的请求&#xff0c;做到局部更新。 比如注册&#xff0c;提示用户名已存在而整个页面没有动 比如百度图片搜索美女&#xff0c;进度条越变越短&#xff…

== 和 equals 的对比 [面试题]

和 equals 的对比[面试题] 文章目录 和 equals 的对比[面试题]1. 和 equals 简介2. Object 类中 equals() 源码3. String 类中 equals() 源码4. Integer 类中 equals() 源码5. 如何重写 equals 方法 1. 和 equals 简介 是一个比较运算符 &#xff1a;既可以判断基本数据类型…

【数据结构OJ题】链表的回文结构

原题链接&#xff1a;https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa?tpId49&&tqId29370&rp1&ru/activity/oj&qru/ta/2016test/question-ranking 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 在做这道…

re中的match和search有什么区别?

问题:请说明以下re模块中的match和search有什么区别? re.match()与re.search()的区别 re.match()只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,结果返回None,而re.search()匹配整个字符串,直到找到一个匹配 re.search() re.search()扫描整个字符串并…