ES6基础之块级作用域
2020/4/1 11:01:26
本文主要是介绍ES6基础之块级作用域,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
众所周知,ES6之前,javascript只有函数作用域。今天我们来聊聊ES6的新特性:块级作用域
var的迷思
ES6之前,声明变量的关键字var,在用var的时候是不是经常出现一些特别的特性,我们来回顾一下
- 声明提升
function print() { console.log(value); // undefined var value = "1"; console.log(value); // 1 } 复制代码
如上例,变量的定义是会提升的,在变量赋值之前使用,不会报错,输出的是undefined。所以前端规范经常会有一条,先赋值后使用,变量的声明一定要在使用之前
- 无块级作用域,只有函数级作用域
function print(condition) { if (condition) { var value = "1"; console.log(value); // 1 } else { console.log(value); // undefined } } 复制代码
- 重复声明和定义
function print() { var value = 1; console.log(value); // doSometing var value = "hello"; console.log(value); } 复制代码
- 无法定义常量
var MAX_NUMBER = 1000; 复制代码
ES6之前定义常量都是使用全部大写的方式标识常量信息,但是这个常量是可以重新赋值的,前端规范中常量使用大写在一方面就是提醒大家在使用的时候注意,大写的是常量不要赋值。
块级作用域
为了解决上述的问题ES6祭出了两个关键词let和const,let替代变量定义,const补充了常量定义
问题1:声明提升
解决方案:TDZ(Temporal Dead Zone),临时死区
-
概念:简言之,在变量或者常量声明语句之前不能使用该常量和变量
-
let和const共有特性
function print() { console.log(typeof value); // 调用的时候会报错 let value = "1"; } 复制代码
如下图所示,红色框所标识的区域是变量“value”的临时死区
问题2:无块级作用域
解决方案:let和const都增加了块级作用域
function print(condition) { if (condition) { let value = "1"; console.log(value); } else { console.log(value); // error:value is not defined } } 复制代码
问题3: 重复声明和定义
解决方案:let和const都不可以在一个块级中进行重复的声明和定义
let a = "1"; let a = "2"; // error: Identifier 'a' has already been declared const b = "1"; const b = "2"; // error: Identifier 'b' has already been declared // 下面的例子是在两个代码块中定义a,所以互相不会影响,不会报错 { let a = "1"; } { let a = "2"; } 复制代码
问题4:无法定义常量
解决方案:关键词const定义的就是常量,在同一块级作用域不能重复赋值
- const定义的常量,不可以再进行赋值操作
const A = "1"; A = "2"; //error: Assignment to constant variable. 复制代码
- const定义的常量必须在声明的同时进行赋值操作
const A; // error:Missing initializer in const declaration 复制代码
注意:常量定义对于值类型和引用类型的数据的处理方式是不一致的 常量定义如果值为对象或者数组,实际上是指针不变,内容可变
const ARR = [1,2]; ARR.push(3); console.log(ARR); 复制代码
循环的迷思
var funcs = []; for (var i = 0; i < 10; i++) { funcs.push(function() { console.log(i); }); } funcs.forEach(function(func) { func(); // outputs the number "10" ten times }); 复制代码
当我们写上面的代码的时候,我们想输出0-9,但是实际上输出的全是10;因为var是没有块级作用域的,实际上我们在输出的时候访问的是同一个i,而i在执行完循环后变成了10,所以都输出的10
在ES6之前我们怎么实现输出0-9,改写上面的代码,在push的时候增加一个函数作用域,使i在指定的函数作用域中有效
var funcs = []; for (var i = 0; i < 10; i++) { funcs.push((function(value) { return function() { console.log(value); } })(i)); } funcs.forEach(function(func) { func(); // outputs 0, then 1, then 2, up to 9 }); 复制代码
ES6的let和const是有块级作用域的,所以使用let和const的时候就不会有这个迷思了
var funcs = []; for (let i = 0; i < 10; i++) { funcs.push(function() { console.log(i); }); } funcs.forEach(function(func) { func(); // outputs 0, then 1, then 2, up to 9 }); 复制代码
注意:普通的for循环是不支持const的,只能使用let。为什么?
普通的for循环实际上可以改写成下面的样子
var funcs = []; { let k; for (k = 0; k < 10; k++) { let i = k; //注意这里,每次循环都会创建一个新的i变量 funcs.push(function() { console.log(i); }); } } funcs.forEach(function(func) { func(); // outputs 0, then 1, then 2, up to 9 }); 复制代码
从上面的代码可以看出,每一次都会对k进行++操作,如果是使用const定义k,那么k++违反了const的不变性,导致错误发生,所以普通循环中不能使用const定义变量
但是对于 for-in,for-of 这样循环就可以使用let和const两种定义方式了,因为不存在++,--这样的操作,不会改变key的值。
var funcs = [], object = { a: true, b: true, c: true }; // doesn't cause an error for (const key in object) { funcs.push(function() { console.log(key); }); } funcs.forEach(function(func) { func(); // outputs "a", then "b", then "c" }); 复制代码
全局块绑定
let,const和var还有一点是不一样的。var如果是在全局作用域中定义的时候,实际上是在全局对象上加了一个属性,在浏览器端就是在window中加了一个属性,这样相当于可以覆盖window中的默认属性。而使用let和const定义的时候不会给全局对象中加属性,也不会覆盖全局对象中的默认属性。
// in a browser var RegExp = "Hello!"; console.log(window.RegExp); // "Hello!" var ncz = "Hi!"; console.log(window.ncz); // "Hi!" // in a browser let RegExp = "Hello!"; console.log(RegExp); // "Hello!" console.log(window.RegExp === RegExp); // false const ncz = "Hi!"; console.log(ncz); // "Hi!" console.log("ncz" in window); // false 复制代码
这篇关于ES6基础之块级作用域的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-28一步到位:购买适合 SEO 的域名全攻略
- 2024-12-27OpenFeign服务间调用学习入门
- 2024-12-27OpenFeign服务间调用学习入门
- 2024-12-27OpenFeign学习入门:轻松掌握微服务通信
- 2024-12-27OpenFeign学习入门:轻松掌握微服务间的HTTP请求
- 2024-12-27JDK17新特性学习入门:简洁教程带你轻松上手
- 2024-12-27JMeter传递token学习入门教程
- 2024-12-27JMeter压测学习入门指南
- 2024-12-27JWT单点登录学习入门指南
- 2024-12-27JWT单点登录原理学习入门