let和const命令

2.1.1 基本用法

ES6新增了let命令,用于生命变量。其用法类似于var,但是所声明的变量只在let命令所在的代码块内有效。

{let a = 10var b = 1}a//ReferenceError:a is not defined
b//1

上面的代码在代码块中分别用let和var声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确得值,这表明,let声明的变量只在其所在的代码块内有效,

2.1.2 不存在变量提升

var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。这种现象多少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。为了纠正这种现象,let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则便会报错。

// var的情况
console.log(foo); //输出undefined
var foo = 2// let 的情况
console.log(bar);// 报错ReferebceError
let bar = 2

在以上代码中,变量foo用var命令声明会发生变量提升,即脚本开始运行时,变量foo便已经存在,但是没有值,所以会输出undefined。变量bar用let命令声明则不会发生变量提升。这表示在声明它之前,变量bar是不存在的,这是如果用到它,就会抛出一个错误。

2.1.3 暂时性死区

只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不在受外部影响,

var tmp = 123if(true){
tmp = 'abc';//ReferenceError
let tmp;
}

上面的代码中存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。
ES6明确规定,如果区块中存在let和const命令,则这个区块对这些命令声明的变量从一开始就形成封闭作用域。只要在声明之前就使用这些变量,就会报错。
总之,在代码快内,使用let命令声明变量之前,该变量都是不可用的。这在语法上称为“暂时性死区”(temporal dead zone,简称TDZ)。

if(true){
// TDZ开始
tmp = 'abc';//ReferenceError
console.log(tmp);//ReferenceErrorlet tmp;// TDZ结束
console.log(tmp);//undefined
tmp = 123;
console.log(tmp);//123

上面的代码中,在let命令声明变量tmp之前,都属于变量tmp的“死区”。
“暂时性死区”也意味着typeof不再是一个百分之百安全的操作。

typeof x;//ReferenceError
let x;

上面的代码中,变量x使用let命令声明,所以在声明之前都属于x的“死区”,只要用到该变量就会报错。因此,typeof运行时就会抛出一个ReferebceError、
作为比较,如果一个变量根本没有被声明,使用typeof反而不会报错。

typeof undeclared // “undefined”

上面的代码中,undeclared是一个不存在的变量名,结果返回“undefined”。所以,在没有let之前,typeof运算符是百分之百安全的,永远不会报错。现在这一点不成立了。这样的设计是为了让大家养成良好的编程习惯,变量一定要在声明之后使用,否则就会报错。

	有些“死区”比较隐蔽,不太容易发现。
function bar(x=y,y=2){return [x,y];}bar();//报错

上面的代码中,调用bar函数之所以报错,是因为参数x的默认值等于另一个参数y,而此时y还没有声明,属于“死区”。如果y的默认值是x,就不会报错,因为此时x已声明。

function bar(x = 2,y = x){return [x,y];}
bar();//[2,2]
另外,下面的代码也会报错,与var的行为不同。
//不报错
var x = x;
//报错
let x = x;
//ReferenceError:x is not defined

以上代码报错也是因为暂时性死区。使用let声明变量时,只要变量在还没有声明前使用,就会报错。以上示例就是属于这种情况,在变量x的声明语句还没有执行完成前就尝试获取x的值,导致出现“x未定义”的错误。
ES6规定暂时性死区和let,const语句不出现变量提升,主要是为了减少运行时错误,放置在变量声明前就是用这个变量,从而导致意料之外的行为。这样的错误在ES5中是很常见的,现在有了这种规定,避免此类错误就很容易了。
总之,暂时性死区的本质就是,只要进入当前作用域,所要使用的变量就已经存在,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

2.1.4 不允许重复声明

let 不允许在相同作用域内重复声明同一个变量
//报错
function (){let a = 10;var a = 1;
}
//报错
function (){let a = 10;let a = 1;
}
因此不能在函数内部重新声明参数
function func(arg){let arg//报错
}
function func(arg){{let arg//报错}
}

2.2块级作用域

2.2.1为什么需要块级作用域

ES5只有全局作用域和函数作用域,没有块级作用域,这导致很多场景不合理。
第一种场景,内层变量可能会覆盖外层变量。

var tmp = new Date();
function f(){console.log(tmp);if(false){	var tmp = 'hello world';}
}
f();//undefined

以上代码的愿意是,if代码块的外部使用外层的tmp变量,内部使用内层的tmp变量,但是,函数f执行后,输出结果为undefined,原因在于变量提升导致内层的tmp变量覆盖率外层的tmp变量。

第二种场景,用来计数的循环变量泄露为全局变量。

var s = 'hello';
for (var i = 0;i<s.lengthl i++){
console.log(s[i]);
}
console.log(i)//5
上面的代码中,变量i只用来控制循环,但是循环结束后,他并没有消失,而是泄露成了全局变量。

2.2.2 ES6的块级作用域

let 实际上为JacaScript新增了块级作用域。
function f1(){
let n = 5;
if(true){let n = 10;}
console.log(n);//5
}
上面的函数有两个代码块,都声明了变量n,运行后输出5.这表示外层代码块不受内层代码块的影响。如果使用var定义变量n,最后输出的值就是10.
ES6允许块级作用域的任意嵌套。
{{{{{let insane = 'Hello Wprld'}}}}};
上面的代码使用了一个5层的块级作用域。外层作用域无法读取内层作用域的变量,
{{{{
{let insane = 'Hello Wprld'}
console.log(insane);//报错
}}}};内层作用域可以定义外层作用域的同名变量。
{{{{
let insane = 'Hello Wprld'
{let insane = 'Hello Wprld'}
}}}};
块级作用域的出现,实际上使得获得广泛的应用的立即执行匿名函数(IIFE)不再必要了。
//IIFE写法function(){var tmp = ...;...
}());//块级作用域写法
{let tmp = ...l...
}

2.2.3 块级作用域与函数声明

  • 允许在块级作用域内声明函数。
  • 函数声明类似于var,即会提升到全局作用域或函数作用的头部。
  • 同时,函数声明还会提升到所在的块级作用域的头部。
    注意!上面3条规则只对ES6的浏览器实现有效,其他环境的实现不用遵守仍旧将块级作用域的函数声明当做let处理即可。

2.2.4 do表达式

本质上,块级作用域是一个语句,将多个操作封装在一起,没有返回值。

{let  t = f();t = t*t+1;
}

上面的代码中,块级作用域将两个语句封装在一起。但是,在块级作用域以外,没有办法得到t的值,因为块级作用域不返回值,除非t是全局变量。

let x = do {let t = f();t*t + 1;
};
上面的代码中,变量x会得到整个块级作用域的返回值

2.3 const 命令

const 声明一个只读的常亮。一旦声明,常量的值就不能改变。
const PI = 3.1415;

PI = 3;//报错

  • const声明的常亮不得改变值。这意味着,const一旦声明常亮,就必须立即初始化,不能留到以后赋值。
  • const的作用域与let相同:只在声明所在的块级作用域内有效。
  • const 命令声明的常亮也不会提升,同样存在暂时性死区,只能在声明后使用。
  • const 声明常量也与let一样不可重复声明。

本质
const 实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。对于简单的类型的数据(数值,字符串,布尔)而言,值就保存在变量指向的内存地址中,因此等同于常量。但对于复合类型的数据(主要是对象和数组)而言,变量指向的内存地址保存的只是一个指针,const只保证这个指针是固定的,至于它指向的数据结构是不是可变的,这完全不能控制。因此,将一个对象声明为常量时必须非常小心。

const foo = {}// 为foo添加一个属性,可以成功
foo.prop = 123;
foo.prop //123//将foo指向另一个对象,就会报错
foo = {};//报错
上面的代码中,常量foo存储的是一个地址,这个地址指向一个对象。不可变的只是这个地址,即不能把foo指向另一个地址,但对象本身是可变的,所以依然可以为其添加新属性,const a = [];
a.push('Hello');//可执行
a.length = 0;//可执行
a = ['DAVE']//报错
上面的代码中,常量a是一个数组这个数组本身是可写的,但是如果将另一个数组赋值给a,就会报错

2.3.3 ES6声明变量的6种方法

  1. var ----ES5
  2. function ----ES5
  3. let
  4. const
  5. import
  6. class

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

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

相关文章

iOS LQG开发框架(持续更新)

基本规则 开发便利性为前提&#xff0c;妥协性能可维护性为前提可读性MVC各部分职责一定要清晰&#xff0c;controll类里面功能尽量抽离成helper&#xff0c;功能一定要清晰&#xff0c;这个非常重要&#xff0c;对代码可读性提升非常高方法内部尽量使用局部变量&#xff0c;最…

【Vue管理后台】用户登录强制修改密码

【Ruoyi管理后台】用户登录强制修改密码 这篇文章已经实现了这个需求&#xff0c;因为个人业务中强制改密页面是进入系统且浮动于其他页面上方&#xff0c;进入强制改密页面的同时其他页面会向后台请求&#xff0c;如果清空token后会造成其他的请求失败。本文整体步骤与参考博文…

经验报告 - SCADE Suite 6 KCG 经历 DO-178B 认证过程中进行的活动

详细内容可参考 ICFP’09 《Experience Report: Using Objective Caml to Develop Safety-Critical Embedded Tools in a Certification Framework》。 数十年前&#xff0c;民用航空电子机构就定义了机载嵌入式代码的认证要求。DO-178B 标准&#xff08;RTCA/DO-178B&#xff…

5.神经网络-激活函数

目录 1. 激活函数不是阶跃函数 1.1 激活函数和阶跃函数都是非线性函数 1.2 激活函数不是阶跃函数 2. sigmoid 函数 2.1 sigmoid 函数表达式 2.2 sigmoid 函数 Python 实现 2.4 sigmoid 函数图 3. ReLU 函数 3.1 ReLU 函数表达式 3.2 ReLU 函数 Python 实现 3.4 ReLU…

线性集合:ArrayList,LinkedList,Vector/Stack

共同点&#xff1a;都是线性集合 ArrayList ArrayList 底层是基于数组实现的&#xff0c;并且实现了动态扩容&#xff08;当需要添加新元素时&#xff0c;如果 elementData 数组已满&#xff0c;则会自动扩容&#xff0c;新的容量将是原来的 1.5 倍&#xff09;&#xff0c;来…

Rust使用HashSet对Vec类型的元素进行去重

在Rust语言中&#xff0c;对Vec类型的元素进行去重&#xff0c;一种常见的方法是使用一个HashSet来帮助我们快速检查元素是否已经存在。以下是使用HashSet对Vec进行去重的示例代码&#xff1a; use std::collections::HashSet;fn main() {let vec_numbers vec![1, 2, 2, 3, 4…

Java后端初始化项目(项目模板)

介绍 emmmm&#xff0c;最近看了一些网络资料&#xff0c;也是心血来潮&#xff0c;想自己手工搭建一个java后端的初始化项目模板来简化一下开发&#xff0c;也就发一个模板的具体制作流程&#xff0c;&#xff08;一步一步搭建&#xff0c;从易到难&#xff09; ok&#xff…

引用类型String的值传递和引用传递

引用传递(pass by reference)是指在调用方法时将实际参数的地址直接传递到方法中,在方法中对参数所进行的修改,将影响到实际参数。 值传递(pass by value)是指在调用方法时将实际参数拷贝一份传递到方法中,在方法中对参数修改,不会影响到实际参数。 基本类型传的是值的拷…

vue2和vue3区别: 探索关键差异

vue2和vue3区别&#xff1a; 探索关键差异 Vue.js 作为流行的前端框架&#xff0c;其版本 3 带来了许多令人兴奋的改进和新功能。虽然 Vue 3 保持了与 Vue 2 的相似性&#xff0c;但也存在一些关键差异需要开发者注意。本文将通过表格形式&#xff0c;清晰地展现 Vue 2 和 Vue …

在多线程程序中,如何保证线程的安全?

在多线程程序中保证线程安全通常涉及以下一些关键技术和策略&#xff1a; 1. 使用同步机制 同步方法&#xff1a;通过在方法签名前添加 synchronized 关键字&#xff0c;确保一次只有一个线程能够执行该方法。同步代码块&#xff1a;通过 synchronized 关键字同步一个代码块&…

刷代码随想录有感(63):将有序数组转换为二叉搜索树(其实时二叉平衡搜索树)

题干&#xff1a; 代码&#xff1a; class Solution { public:TreeNode* traversal(vector<int>& nums, int left, int right){if(left > right)return NULL;int mid left (right - left)/2;TreeNode* NewRoot new TreeNode(nums[mid]);NewRoot->left tra…

文心一言指令:解锁自然语言处理新时代的技术探索

在人工智能领域&#xff0c;自然语言处理&#xff08;NLP&#xff09;一直是研究与应用的热点&#xff0c;它致力于让机器理解、生成并运用人类语言&#xff0c;架起人机交互的桥梁。随着技术的飞速发展&#xff0c;一个全新的概念——“文心一言指令”应运而生&#xff0c;这一…

【GO】go语言中的HTTP标准库 - http编程

上一节已经学习了HTTP的基础知识&#xff0c;本章将学习关于go语言的HTTP编程&#xff0c;最重要的是掌握 net/http 包的用法&#xff0c;以及如何自己编写一个简单的Web服务端&#xff0c;通过客户端访问Server端等。 编写简单的Web 服务器 http.ListenAndServe 启动 Http S…

制作跳动的爱心网页效果

html <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>跳动的爱心</title> <link rel&q…

K-means聚类模型:深入解析与应用指南

K-means聚类是一种广泛使用的无监督学习算法&#xff0c;它通过迭代过程将数据集划分为K个聚类。以下是一篇关于K-means聚类模型的技术文章&#xff0c;将从不同的角度进行详尽的描述。 1. 引言 K-means聚类算法是一种简单且高效的聚类方法&#xff0c;广泛应用于数据挖掘、市…

Chatgpt的应用场景

文案创作类&#xff1a; 作为一名大型语言模型&#xff0c;ChatGPT可以为使用者提供多种文本处理和文字创作方面的服务&#xff0c;例如&#xff1a; 文本生成和创作 ChatGPT可以基于您提供的主题、关键词或文本段落&#xff0c;生成符合使用者要求的新文本。这些文本可以是文…

Linux:Figshare网站文件下载(非浏览器)

参考aws亚马逊云下载figshare内容 Linux wget -c 下载网页内容crul -C_figshare怎么下载数据-CSDN博客 尝试一下 mamba search awscli mamba install awscli2.15.48 aws --version通过网页获取下载链接 比如&#xff1a; https://s3-eu-west-1.amazonaws.com/pfigshare-u-…

Centos 停服倒计时!你的操作系统何去何从?

在计算机技术的不断演进中&#xff0c;操作系统扮演着至关重要的角色。然而&#xff0c;对于许多企业和个人用户来说&#xff0c;CentOS的突然停服消息带来了一场不小的冲击。作为一款备受欢迎的企业级Linux发行版&#xff0c;CentOS的停服意味着用户需要重新评估自己的操作系统…

如何清除DNS缓存,刷新DNS

大家在使用域名访问服务器的时候&#xff0c;经常会遇到一个问题&#xff0c;同一个局域网里的两台电脑&#xff0c;一台可以访问而另一台不行。这是为什么呢&#xff1f;这里我要和大家说下DNS缓存的问题&#xff0c;顾名思义&#xff0c;每台电脑都有DNS缓存&#xff0c;在域…

Torch添加、修改子模块

1. add_module link 2.net[2] 对nn.Sequential的索引 import torch.nn as nn model nn.Sequential(nn.Conv2d(1,20,5),nn.ReLU(),nn.Conv2d(20,64,5),nn.ReLU())print(model) print(model[2]) # 通过索引获取第几个层 运行结果为&#xff1a; Sequential((0): Conv2d(1, 2…