你真的懂let和const吗?

块级作用域

在ES6之前我们脑海里应该只存在全局作用域和函数级作用域,没有块级作用域。那么为什么要引入块级作用域呢?

避免外层变量被覆盖

var str = "hello";

function d() {

 console.log(str);

 if (false) {

   var str = 'world';

 }

}

d();//undefined

相信很多刚入门的同学看到上述代码会有所不解,其实在全局作用域str变量已经被声明且复制,为什么我函数里面访问不到呢。这里就牵扯到变量提升和函数级作用域的概念。上述代码其实等同于下放代码,当函数被执行的时候生成了一个新的作用域也就是函数作用域,js引擎会把变量声明提到方法体的最前面,大家可以看到只是声明了并没有赋值。所以就是

undefined。

var str = "hello";

function d() {

 var str ;

 console.log(str);

 if (false) {

   str = 'world';

 }

}

d();//undefined

循环变量污染全局变量

var str = 'hello';

for (var i = 0; i < str.length; i++) {

 console.log(str[i]);

}

console.log(i); // 5

很多同学面试的时候可能会遇到上面类似的代码,疑惑点应该在为什么会打印出来为什么会是5,同样的道理代码如同下方。变量会被提升,所以在循环结束之后i就被累加到了5.

var str = 'hello';

var i;

for ( i = 0; i < str.length; i++) {

 console.log(str[i]);

}

console.log(i); // 5

es6的let和const声明符,是不存在变量提升的;同时也只在块级作用域生效。

这个答案应该很明显了吧

var str = "hello";

function d() {

 console.log(str);

 if (false) {

   let str = 'world';

 }

}

d();

暂时性死区MDN

什么是暂时性死区呢?很多人可能很迷惑。那就听我娓娓道来,如果说我们使用了let和const命令,作用域内会对这些命令声明的变量,在它的声明周期内形成一种封闭作用域。这在语法上,称为“暂时性死区”。代码展示如下:

if (true) {

 tmp = 'abc'; // ReferenceError

 console.log(tmp); // ReferenceError

 let tmp;

 console.log(tmp); // undefined

 tmp = 123;

 console.log(tmp); // 123

}

因为let和const声明是不会被提升的,所以为了保障声明的有效性,js的解释引擎会对变量所处的块级作用域形成一种保护,因此在声明之前使用会有语法错误,是不被允许的。

不能重复声明

function de(){

var a = "1";

var a = "2";

console.log(a);

}

de()//不报错

function de(){

var a = "1";

let a = "2";

console.log(a);

}

de()//报错

function de(){

let a = "1";

let a = "2";

console.log(a);

}

de()//报错

相信大家一般不会声明重复变量编码,所以在这里就不做解释了。如果大家感兴趣可以自己研究或者来现场一起学习。

const常量

const声明符的大多特性和let相同,这里就不多做解释了。大家都知道const是声明常量的,一但变量被声明成常量它就不能再被继续修改了。大家要注意的是这里变量不可被修改的是存储的地址值不可被修改,意思就是简单类型的数据是不能修改的。复合类型的数据(主要是对象和数组)const只能保证这个指针是固定的,而这个具体的对象实例包含的属性是可以被修改的。看看代码我们可能会更清楚:

//实例一

const a = "hello";

console.log(a);//"hello"

a = "world";//Assignment to constant variable

//实例二

const obj = {};

obj.name = "jack";

console.log(obj.name);//"jack"

obj = {};//Assignment to constant variable.

//实例三

const a = [];

a.push('Hello');

console.log(a); //[ 'Hello' ]

a.length = 0;

a = ['Dave'];    // Assignment to constant variable.

正如大家所看到的字符串a被复制后就不能在修改,而对象和数组是可以改变它里面的元素的,但是不能给重新复制一个新的对象实例。由此就可以断定const声明出来的变量存的是固定的地址值。

关于es6还有更多的知识点,请关注我接下来的文章。如发现不当之处欢迎加微信(xiaoqiang0672)批评。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏深度学习之tensorflow实战篇

Python中的__init__()方法整理中(两种解释)

解释一:看懂了就不用看第二种了 __init__()方法是Python学习当中重要的基础知识,__init__()方法意义重大的原因有两个。第一个原因是在对...

9266
来自专栏编程

程序员C语言C加加新手小白入门基础最容易犯的17种错误,你中了几个?

相信这么努力的你 已经置顶了我 C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考...

2205
来自专栏PHP实战技术

你真的懂let和const吗?

块级作用域 在ES6之前我们脑海里应该只存在全局作用域和函数级作用域,没有块级作用域。那么为什么要引入块级作用域呢? 避免外层变量被覆盖 var str = "...

3956
来自专栏前端桃园

ES6之块级作用域

1504
来自专栏Deep learning进阶路

C++随记(二)---动态分配内存问题(1)

C++随记(二)---动态分配内存问题(1) 面向对象的编程的一个特点就是在运行阶段(而不是编译阶段)进行决策。运行阶段决策提供了灵活性,可以根据当时的情况进行...

1880
来自专栏北京马哥教育

深入 Python 字典的内部实现

字典是通过键(key)索引的,因此,字典也可视作彼此关联的两个数组。下面我们尝试向字典中添加3个键/值(key/value)对: 这些值可通过如下方法访问: 由...

36015
来自专栏bboysoul

1461: C语言实验题――求平均值

描述:求n个数的平均数。 输入:输入数据有2行,第一行为n,第二行是n个数。 输出:输出n个数中的平均数,结果保留小数点2位。 样例输入:5-1 2.1 ...

1512
来自专栏程序员互动联盟

【专业技术】C++里面重要的几个关键字的用法

编者按: 这几个关键字非常重要,程序中经常见到他们的身影,但是确切意思有时候还需要多搜索下才能知道。笔者这里把它搬出来,也是希望大家引起重视,努力掌握它。 C+...

3617
来自专栏IT派

JavaScript 打怪升级 —— 把业务逻辑当练习题做

开发项目和出没社区有一段时间了,会遇上一些比较有印象业务需求。这些业务需求,可能是自己开发项目遇上的,可能是在社区看到的业务需求,或者其他情况接触到的需求,但是...

803
来自专栏小俊博客

Nginx的location规则迷之匹配

Nginx,一个改变世界的软件,其作者是一个俄罗斯人,俗称毛子,在国人的印象中,是一群晚饭后牵着大灰熊在小区楼下散步的彪汉。能写出这般顺滑的软件,可谓是心有猛虎...

5812

扫码关注云+社区