let和const

  1. 不可以重复声明
  2. 不会发生变量提升,因此必须在声明之后使用,否则报错!
  3. 只在声明所在的块级作用域内有效

let

同一个作用域内不能重复声明同一个变量:

function func() {
let a = 10;
var a = 1;
}
func() // 报错 function func() {
let a = 10;
let a = 1;
}
func() // 报错
function func(arg) {
let arg;
}
func() // 不能在函数内部重新声明参数!!!!!因为参数等同于在函数内部var声明的一个局部变量 function func(arg) {
{
let arg;
}
}
func() // 该例子不报错,是因为在func里面增加{}等同于又新建了一个作用域,因此{}里的arg不是参数arg

let可以只声明不赋值,没有值的时候会输出undefined

console.log(let1)  // let1 is not defined
let let1;
console.log(let1) // undefined
let1 = 1;
console.log(let1) // 1

let在for循环中的应用:【下面将给出我对这两个例子的理解】

var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); //

该demo的执行过程如下:

var a = [];   // 全局变量

var i = 0;    // 全局变量,第1次循环

a[0] = function(){ console.log(i) }   // 此时的i不是0,是因为这里只是声明了这个函数,并没有执行它,即没有创建这个函数的上下文,因此i不会沿着作用域链向外去找i的值

var i = 1;  // 第2次循环,因为是全局变量,因此i = 1会替换上一个i = 0

a[1] = function(){ console.log(i) }  // 同a[0],所有该函数的执行的作用域是全局作用域

var i = 2  // 第3次循环,同理,i = 2会替换上一个i = 1

...

var i = 9;  // 第10次循环,i = 9会替换上一个i = 8

a[9] = function(){ console.log(i) }

直到var i = 10,10<10不满足循环条件,则跳出循环,继续向下执行全局作用域下面的语句:a[6]();

调用a[6]函数,并创建a[6]函数的函数上下文,执行该函数内部的console.log(i),这个函数中没有i,因此顺着作用域链向外去找i,而此时全局变量var i = 10,因此输出10

var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); //

第二个demo的执行过程如下:

let a = [];   // 全局变量

{  // 第1次循环

  let i = 0;  // let使得for循环变成一个块级作用域,则let i = 0是这个块级作用域下的局部变量

  a[0] = function(){ console.log(i) }   // 注意!!!由于let的声明创建了一个块级作用域,此时的a[0]这个函数就是一个闭包

}

{  // 第2次循环

  let i = 1;   // 注意!!!此时的let i = 1和let i = 0是属于两个不同的块级作用域,因此两者的值并不会相互影响

  a[1] = function(){ console.log(i) }   // 同a[0]

}

...

{  // 第10次循环

  let i = 9;

  a[9] = function(){ console.log(i) }  // 同样该函数也是一个闭包!

}

{

  直到let i = 10,不满足循环条件,跳出循环,注意!!该代码块中不存在闭包因此,let i = 10在这次循环之后代码块随即被销毁

}

继续向下执行全局作用域下面的语句:a[6]();

调用a[6]函数,进入该块级作用域的代码环境,在该闭包内部找i值,如果没有则顺着作用域链向外去找i,而此时块级作用域内有let i = 6,因此输出6

此时闭包被调用,所以整个代码块中的变量i和a[6]函数被销毁。

 

暂时性死区

在代码块内,凡是用let声明变量之前,该变量都是不可使用的,这在语法上叫做“暂时性死区”(Temporal Dead Zone,简称TDZ)。所以,凡是在声明之前使用该变量,就会报错!

var tmp = 'ning';

if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError 去掉这两句才能继续向下执行代码并输出响应的结果 let tmp; // TDZ结束
console.log(tmp); // undefined tmp = 123;
console.log(tmp); //
}

从上面的代码可以看出虽然全局有一个tmp变量,但是在if这个块级作用域下let声明了一个局部变量tmp,导致该局部变量tmp绑定(binding)了这个区域,所以在let声明之前使用它,都属于该tmp的死区,会报错!

在没有let之前,使用typeof是百分之百不会报错的,因为如果typeof一个未声明的变量,会输出'undefined'

但是,暂时性死区的出现使得typeof的使用需要小心!因为如果在let声明前typeof该变量则会报错!

typeof x; // ReferenceError
let x;

const

const声明一个只读的常量。一旦声明其值就不能改变,并且一旦声明变量就必须立即初始化,只声明不赋值就会报错!

console.log(const1)  // Missing initializer in const declaration
const const1;
console.log(const1) // Missing initializer in const declaration

cosnt也是在块级作用域内有效,例子如下:

        if (true) {
const MAX = 5;
}
console.log(MAX); // Uncaught ReferenceError: MAX is not defined

const命令声明的常量不能提升,只能在声明的位置之后使用const,例子如下:

        if (true) {
console.log(MAX); // Uncaught ReferenceError: MAX is not defined
const MAX = 5;
}

const同样不能重复声明!例子如下:

function func() {
const a = 10;
var a = 1;
}
func() // 报错 function func() {
const a = 10;
let a = 1;
}
func() // 报错

const的本质:

实际上是保证的是变量指向的内存地址保存的数据不能改动!

对于基本数据类型而言,内存地址里保存的就是值,所以等同于常量

而对于引用类型而言(主要是对象和数组),变量指向的内存地址中保存的是 指向实际数据的指针,因此只要该指针是固定不变的,该指针指向的堆内存的数据是否变化const是不在意的!因此,将一个对象声明为常量必须非常小心!!!!例子如下:

        const obj = {};

        obj.attr = 'ning';
console.log(obj.attr) // 'ning' obj = { attr: 'li' }
console.log(obj.attr) // Uncaught TypeError: Assignment to constant variable.

常量obj存的是一个地址,指向一个对象,不可变的是这个地址,而对象本身里的内容是可变的!

let和const的一些知识点的更多相关文章

  1. C++随笔(0)——关于const

    最近发现自己对const这一块其实不甚熟悉,所以复习一下const的相关知识点. 基本用法 const int bufSize = 512; 上面这样就可以将bufSize定义为常量,编译的时候编译器 ...

  2. vue2.0自学笔记

    前言: 一.优点: 轻量级.高效率.上手快.简单易学.文档全面而简洁 二.功能: 1.模板渲染 2.模块化 3.扩展功能:路由.Ajax 三.课程包含: 1.Vue实例 2.Vue组件 3.Vue指令 ...

  3. Effective C++(1-2) 编译器替换预处理器

    1 C++最主要的四部分: C Object-Oriented C++: 面向对象 Template C++:泛型编程 STL C++高效编程守则视状况而变化,取决于你使用C++的哪一部分. 2 尽量 ...

  4. C++面向对象高级编程(一)基础篇

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. 概要: 知识点1 构造函数与析构函数 知识点2 参数与返回值 知识点3 const 知识点4 函数重载(要与重写区分开) 知识点5 友元 先以C ...

  5. 前端学习笔记 --ES6新特性

    前言 这篇博客是我在b站进行学习es6课程时的笔记总结与补充. 此处贴出up主的教程视频地址:深入解读ES6系列(全18讲) 1.ES6学习之路 1.1 ES6新特性 1. 变量 2. 函数 3. 数 ...

  6. 【ES6】ES6入门笔记

    1.概要 - ECMAScript2015(ES6)是Javascript最标准的语法式样,是在2015年6月由Ecma国籍组织公布的最新版本,现在已经被多个领域和浏览器所广泛采纳和使用. 2.学习网 ...

  7. openssl 1.1.1 reference

    openssl 1.1.1 include/openssl aes.h: # define HEADER_AES_H aes.h: # define AES_ENCRYPT 1 aes.h: # de ...

  8. 两个知识点的回顾(const指针和动态链接库函数dlopen)

    昨天,看了一点<c++ primer>和<程序员的自我修养>,想起了自己以前的两个知识点,这里回顾,并且总结一下. 1. const指针的参数 看primer的时候,看到几个概 ...

  9. C#基本知识点-Readonly和Const的区别

    什么是静态常量(Const)和动态常量(Readonly)   先解释下什么是静态常量(Const)以及什么是动态常量(Readonly). 静态常量(Const)是指编译器在编译时候会对常量进行解析 ...

随机推荐

  1. [JZOJ3337] 【NOI2013模拟】wyl8899的TLE

    题目 题目大意 给你两个字符串\(A\)和\(B\),可以修改\(A\)中的一个字符,求修改后最长的\(A\)的前缀,使它是\(B\)的子串. 思考历程 看到这道题之后,第一眼想到的就是后缀自动机! ...

  2. 【JZOJ6375】华灵[蝶妄想]

    description analysis 明显括号序长度是偶数,如果其中一个是奇数,那么只能让这奇数行或列是括号序 对于两个都是偶数,需要分类讨论,假设\(n<m\) 有一种是牺牲掉\(n\ov ...

  3. CSS——滑动门技术及应用

    先来体会下现实中的滑动门,或者你可以叫做推拉门: 滑动门出现的背景 制作网页时,为了美观,常常需要为网页元素设置特殊形状的背景,比如微信导航栏,有凸起和凹下去的感觉,最大的问题是里面的字数不一样多,咋 ...

  4. oracle 删除掉重复数据只保留一条

    用SQL语句,删除掉重复项只保留一条 在几千条记录里,存在着些相同的记录,如何能用SQL语句,删除掉重复的呢 .查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断 select ...

  5. django-filter 实现过滤时查询是否包含在数组的方法,in数组的实现

    查了半天无解,还是在官网找到的,记录一下 使用 BaseInFilter 官网地址:https://django-filter.readthedocs.io/en/master/ref/filters ...

  6. NEO4J全文检索架构

    NEO4J全文检索架构 一.有大量存量数据(亿级以上)(并长期有增量数据进入) 二.无大量存量数据或者少量存量数据(或全部为增量数据) 三.架构方案选择优先级 以下方案,是根据实践总结的基于NEO4J ...

  7. Qt plugins(插件)目录

    今天在打包Qt程序时,出现了因为缺少插件,导致背景图无法显示的问题.第一次将plugins目录全部拷贝到了应用程序根目录下,还是无法运行.查阅资料,需要拷贝plugins子目录到应用程序跟目录.虽然最 ...

  8. 《你不知道的JavaScript》上卷——第1章

    知识点总结 1.什么是作用域? 作用域是根据名称查找变量的一套规则. 2.通常将JavaScript归类为“动态”或“解释执行”语言,但事实上它是一门编译语言. 3.编译 在传统编译语言的流程中,程序 ...

  9. 性能分析神器VisualVM【转】

    性能分析神器VisualVM[转] Posted on 2015-04-17 09:37 WadeXu 阅读(5809) 评论(6) 编辑 收藏 VisualVM 是一款免费的,集成了多个 JDK 命 ...

  10. JavaWeb中请求转发和请求重定向的区别

    针对于JavaWeb中请求与重定向的一个cheatsheep: 1.转发 1)完成一次转发,用户浏览器发送一次请求 2)转发之后,浏览器URL地址栏不改变(服务器帮忙完成) 3)请求域中数据不丢失 4 ...