NodeJS学习————关于let和const命令的使用理解

let的基本用法

在新的js规范ES6中,新增了let 命令,用来声明变量。用法类似于var,但不同的是所声明的变量,只在let 命令所在的代码块内有效。

 

{

let a = 10;

var b = 10;

}

//ReferenceError: a is not defined

console.log(a + b);

在之前的js版本中,通过var命令声明的变量可以在声明之前使用,只不过是undefined

 

console.log(a)// 输出undefined

var a = 10;

这种现象被称为“变量提升”,即变量可以在声明之前使用,值为undefined。而通过let声明的变量,无法在声明之前使用,如果这么做了,则会报xx is not defined错误。

而变量声明之前的代码块,都被称为“暂时性死区”,即变量无法使用的地方。与var声明的全局变量不同,let被设计为一种在局部使用的变量声明命令,使它所声明的变量更具有可操作性。与Java中声明变量的方式非常类似。

一些隐蔽的死区,不容易发现,如:

 

function bar(x = y, y = 2) {

return [x, y];

}

 

bar();

 

输出如下:

for循环中的let变量

for循环的计数器,非常适合使用let命令。

 

for (let i = 0; i < 10; i++) {

console.log(i);

}

上述代码中,i只在for循环体内有效。而且,应当注意的是,let声明的i在每轮循环都是一个新的变量,每一轮都会重新声明 i ,JavaScript引擎内部会记住上一轮循环的值,初始化本轮的变量i 时,就在上一轮的基础上进行计算。为什么每轮都会声明变量i?这是因为js中的for循环有一个特性,设置循环变量的小括号内是父作用域,而循环体的大括号内是子作用域,这是两个不同的作用域。

不允许重复声明

let不允许在同一个作用域内对同一个变量重复声明。

 

// 报错

function testRedefined(){

let a = 10;

let a = 20;

}

 

testRedefined_2();

// 不报错

function testRedefined_2() {

let a = 10;

{

let a = 20;

console.log(a); // 20

}

console.log(a);// 10

}

块级作用域

ES5只有全局作用域和函数作用域,没有块级作用域,这会造成诸多问题:

内层变量可能会覆盖外层变量;仅用于计数的循环变量被泄漏为全局变量。

let实际为ES6新增了块级作用域。它允许块级作用域的任意嵌套

 

{{{{{{let a = 33;}}}}}}

不同作用域彼此独立,互不影响,因此可以在不同的作用域定义相同的变量名。

const命令基本用法

const声明一个只读的常量。一旦声明,常量的值就不能改变。

 

const PI = 3.1415;

PI // 3.1415

 

PI = 3;

// TypeError: Assignment to constant variable.

const声明的变量不得改变值,这意味着,const一旦声明了变量,就必须立即初始化,不能留到以后赋值,如下所示:

 

const PI;

// SyntaxError: Missing initializer in const declaration

 

const声明的变量和let有类似的限制,命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用,同样在一个相同的作用域内不能重复声明。

 

const命令的本质

const实际保证的并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。

对于简单的数据类型(数值,字符串,布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。这与Java语言中的final修饰的变量非常相似。因此,在将一个对象或数组生命为const时,应该非常小心。

如果真的希望对象是一个不变的常量,我们可以使用Object.freeze()方法,下面是一个将对象本身及其属性冻结的通用写法:

 

var constantize = (obj) => {

Object.freeze(obj);

Object.keys(obj).forEach( (key, i) => {

if ( typeof obj[key] === 'object' ) {

constantize( obj[key] );

}

});

};

 

 

顶层对象

 

顶层对象可以理解为js代码所运行的宿主环境对象。

在浏览器环境中,这个顶层对象就是window对象,在Node中就是global对象。在ES5中顶层对象的属性就是全局变量(通过var声明的变量)

 

window.a = 1;

a // 1

 

a = 2;

window.a // 2

上述代码中,顶层对象的属性赋值与全局变量的赋值,是同一件事。

这种顶层对象的属性与全局变量挂钩,被认为是JavaScript语言最大的设计败笔之一。

ES6为了改变这一点,一方面为了兼容,规定var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,ES6开始,全局变量将逐步与顶层的属性脱钩。

 

var a = 1;

// 如果在 Node 的 REPL 环境,可以写成 global.a

// 或者采用通用方法,写成 this.a

window.a // 1

 

let b = 1;

window.b // undefined

ES5的顶层对象在各种实现里是不统一的,因此其本身也是个问题。

-浏览器里面,顶层对象是window,但Node和Web Worker没有window

-浏览器和Web Worker里面,self也指向顶层对象,但是Node没有self

-Node里面,顶层对象是global,但其他环境都不支持。

同一段代码为了能够在各种环境都能取得顶层对象,现在一般是使用this变量,但是有局限性。

-全局环境中,this会返回顶层对象。但是,Node模块和ES6模块中,this返回的是当前模块。

-函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是严格模式下,这时this会返回undefined

-不管是严格模式还是普通模式,new Function('return this')(),总是会返回全局对象。但是如果浏览器用了CSP内容安全政策,那么eval、new Function这些方法都可能无法使用。

 

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

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

相关文章

forward和redirect的区别是什么?

forward和redirect是什么&#xff1f; 是servlet种的两种主要的跳转方式。forward又叫转发&#xff0c;redirect叫做重定向。 区别&#xff1a;&#xff08;本地效应次数&#xff09; 地址栏&#xff0c;数据共享&#xff0c;应用场景&#xff0c;效率&#xff0c;本质&…

MYSQL的索引类型:PRIMARY, INDEX,UNIQUE,FULLTEXT,SPAIAL 有什么区别?各适用于什么场合?

一、MySQL索引类型 MySql常见索引类型有&#xff1a;主键索引、唯一索引、普通索引、全文索引、组合索引 PRIMARY KEY&#xff08;主键索引&#xff09; ALTER TABLE table_name ADD PRIMARY KEY ( column ) UNIQUE(唯一索引) ALTER TABLE table_name ADD UNIQUE (colu…

Servlet入门总结

一、了解Servlet的概念Servlet定义&#xff1a;Servlet是基于Java技术的Web组件&#xff0c;由容器管理并产生动态的内容。Servlet引擎作为WEB服务器的扩展提供支持Servlet的功能。Servlet与客户端通过Servlet容器实现的请求/响应模型进行交互。 注意&#xff1a;Servlet不是从…

MySQL日期类型的处理总结

一、概述 MySQL中的日期类型包括以下5种&#xff1a; 类型大小 (字节)范围格式用途DATE31000-01-01/9999-12-31YYYY-MM-DD日期值TIME3-838:59:59/838:59:59HH:MM:SS时间值或持续时间YEAR11901/2155YYYY年份值DATETIME81000-01-01 00:00:00/9999-12-31 23:59:59YYYY-MM-DD HH:…

详解HTTP协议~~~

详解HTTP协议~~~HTTP 简介HTTP协议是Hyper Text Transfer Protocol&#xff08;超文本传输协议&#xff09;的缩写,是用于从万维网&#xff08;WWW:World Wide Web &#xff09;服务器传输超文本到本地浏览器的传送协议。。HTTP是一个基于TCP/IP通信协议来传递数据&#xff08;…

MyBatis基础知识概述

一、依赖配置 添加依赖即可&#xff0c;jar包或pom依赖&#xff1a; <dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>x.x.x</version> </dependency> 二、SqlSessionFactory 2.1 什…

Mybatis Plus————代码生成器

代码生成器 MyBatis Plus是MyBatis的扩展框架&#xff0c;而代码生成器是MP的核心功能之一&#xff0c;另外还有 “条件构造器”和“通用CRUD”等功能。 步骤演示 mp的代码生成器有两种方式自动生成代码&#xff0c;一种是通过main方法来执行程序&#xff0c;另一种是通过maven…

Spring MVC 流程图解析

Spring MVC 流程图解析Spring MVC工作流程图图一图二 SpringMVC工作流程描述DispatcherServlet&#xff0c;HandlerMapping&#xff0c;HandlerExecutionChain&#xff0c;HandlerAdapter&#xff0c;HttpMessageConveter&#xff0c;BindingResult&#xff0c;ModelAndView&am…

Java并发编程实战————可重入内置锁

引言 在《Java Concurrency in Practice》的加锁机制一节中作者提到&#xff1a; Java提供一种内置的锁机制来支持原子性&#xff1a;同步代码块。“重入”意味着获取锁的操作的粒度是“线程”&#xff0c;而不是调用。当某个线程请求一个由其他线程持有的锁时&#xff0c;发出…

java的守护进程与非守护进程

java的守护进程与非守护进程 最近重新研究Java基础知识&#xff0c;发现以前太多知识知识略略带过了&#xff0c;比较说Java的线程机制&#xff0c;在Java中有两类线程&#xff1a; User Thread(用户线程)、Daemon Thread(守护线程) &#xff0c;&#xff08;PS:以前忽略了&a…

双剑合璧————Spring Boot + Mybatis Plus

引言 最近在学习Mybatis Plus的使用&#xff0c;希望通过spring boot快速将mybatis plus整合进来。 对于springboot项目&#xff0c;mybatis plus团队也有自己的启动器 &#xff1a;mybatis-plus-boot-starter。这个依赖内部已经整合了mybatis-spring&#xff0c;也包括非快速…

Java中常用的类,包,接口

Java中常用的类&#xff0c;包&#xff0c;接口包名说明java.lang该包提供了Java编程的基础类&#xff0c;例如 Object、Math、String、StringBuffer、System、Thread等&#xff0c;不使用该包就很难编写Java代码了。java.util该包提供了包含集合框架、遗留的集合类、事件模型、…

Collection框架介绍

Collection&#xff1a;List列表&#xff0c;Set集&#xff0c; Map&#xff1a;Hashtable&#xff0c;HashMap&#xff0c;TreeMapCollection 是单列集合 List 元素是有序的、可重复 有序的 collection&#xff0c;可以对列表中每个元素的插入位置进行精确地控制。 可以根据…

Git初学札记(一)————Git简介与安装

前言 Git是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本管理。Git是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。&#xff08;在这里再一次致敬Linus大神&#xff09;特点 分布式相比于集中式的最…

Hashtable、HashMap、TreeMap总结

Hashtable、HashMap、TreeMap总结三者均实现了Map接口&#xff0c;存储的内容是基于key-value的键值对映射&#xff0c;一个映射不能有重复的键&#xff0c;一个键最多只能映射一个值。 &#xff08;元顺初线&#xff09;&#xff08;1&#xff09; 元素特性HashTable中的key、…

Git初学札记(二)————EGit导入远程Git仓库项目(Clone操作)

引言 我们在实际开发项目的时候&#xff0c;难免要使用像Eclipse或者IDEA这样的继承开发工具&#xff0c;除了部分“牙牙学语”的程序员需要手动输入javac去编译程序以外&#xff0c;在实际开发中手动编译并运行项目的“猿族”应该是已经绝种了。 我个人认为&#xff0c;使用gi…

int和Integer的比较

int和Integer的比较1 int和IntegerJDK1.5引入了自动装箱与自动拆箱功能&#xff0c;Java可根据上下文&#xff0c;实现int/Integer,double/Double,boolean/Boolean等基本类型与相应对象之间的自动转换&#xff0c;为开发过程带来极大便利。最常用的是通过new方法构建Integer对象…

Git初学札记(三)————创建Git版本库

引言 版本库即所谓的Git仓库&#xff0c;英文名称是Repository&#xff0c;可以简单理解为一个目录&#xff08;.git folder&#xff09;&#xff0c;这个目录可以记录并保存直接父级及其子目录下的全部文本文件的修改操作&#xff0c;谓之“版本控制”&#xff01; 手动建库 不…

Git初学札记(四)————Git Push的常规操作与Pull冲突解决

目录 引言 Git命令行的远程Push EGit Push操作中的冲突问题 同步 工作区与本地库同步 工作区与远程库同步 图标 重点 引言 在团队开发当中&#xff0c;Git Push是多人协作环节中的最重要的一环可能没有之一。同SVN一样&#xff0c;push操作可以看做是对远端程序的提交…

一篇博客读懂设计模式之---动态代理与反射

一篇博客读懂设计模式之---动态代理与反射 先来讲一下反射&#xff1a; 1 关于反射反射最大的作用之一就在于我们可以不用在编译时就知道某个对象的类型&#xff0c;而在运行时通过提供完整的”包名类名.class”得到。注意&#xff1a;不是在编译时&#xff0c;而是在运行时。…