「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战」
1、let变量的使用
let变量和var的使用区别:
- let和var都用于声明变量,但是let所声明得变量只在代码块内有效;
{
let a = 10;
var b = 10;
}
console.log(a);//报错:a is not defined
console.log(b);//1
2.不存在变量提升——在声明之前可以使用,值为undefined
let 声明变量,必须先声明后使用,否则便会报错;
//var 的情况
console.log(foo);//输出undefinedif
var foo =2;
//let 的情况
console.log(bar); //报错
let bar = 2;
3.暂时性死区TDZ(temporal dead zero)——在进入作用域之前,所要使用的变量就已经存在,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
if(true){
//TDZ 开始
tmp='abc'; // 报错
console.log(tmp); //报错
let tmp ; //TDZ结束
console.log(tmp); //undefined
temp = 123;
conlose.log(tmp); //123
}
在let 命令声明 tmp 之前,都属于变量tmp的‘死区’。
4.不允许重复声明
let不允许在相同作用域内重复声明同一个变量。
//报错
function (){
let a = 10;
var b =10;
}
因此,不能在函数内部重新声明参数。
function axx(arg){
let arg;//报错
}
function BXX(arg){
{
let arg;//不报错
}
}
补充;let的使用语法,最常见使用在for循环里。
块级作用域
1.使用的原因:
- 内层变量可能会覆盖外层变量
-
var a=new Date(); function f(){ console.log(a); if(false){ var a='hello' } } f();//undefined 说明:内层变量var a='hello'在声明之前打印,变量提升导致修改了外层的变量的值。 - 用来计数的循环变量泄露为全局变量
-
var a='hello' for(var i=0;i<a.length;i++){ console.log(s[i]); } console.log(i); //5 i用来控制变量的循环,但是循环结束后他没有消失,而是泄露成了全局变量。
2.ES6的块级作用域:
外层的作用域无法读取内层的作用域的变量,且内层作用域可以定义外层作用域的同名变量。
说明:块级作用域的出现,使立即执行的匿名函数不在必要了。
//ITFE匿名函数写法
(function (){
}());
//块级作用域
{
let tmp - ....;
}
3.块级作用域与函数声明
ES5规定:函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域中声明。
而ES6中规定:
- 允许在块级作用域内声明函数。
- 函数声明类似于var,可以提升到全局作用域或者函数作用域的头部。
- 函数声明还会提升到所在的块级作用域的头部。
2、const命令:
1.基本用法:
- 声明一个常量,声明之后不能改变,即一旦声明之后就必须立即初始化。
- 与let 作用域相识,只在生命所在的块级作用域有效。
- 存在暂时性死区,必须在声明后使用。
2.本质
const并不是保证变量的值不会变化,而是变量指向的内存地址不变。
const foo = {};
//添加一个属性可以成功
foo.prop=123;
//foo指向另一个对象时,就会报错
foo = {}
说明:只是对象的地址不可变,对象本身的属性是可变化的。
foo.push('hello'); //正确
foo = { 'a' } //错误
3.es6声明变量的6种方法:
es5:var 和 function命令,es6中添加了 let 和 const 命令;import 和 class 命令。
3、顶层对象属性:
顶层环境对象在浏览器中指的是window对象,在node环境中指的是global对象。
es6规定,var和function声明是(全局)顶层对象的属性,而let、const、等声明的不是顶层对象属性。
4、var 、const 和 let 在for-in/for-of 的区别
<script>
function fooConst() {
console.log("这是 const 循环 obj 和 arr")
for (const key in {a: 1, b: 2}) {
console.log(key);
}
// a, b
for (const value of [1,2,3,4,5]) {
console.log(value);
}
// 1, 2, 3, 4, 5
}
fooConst();
function fooLet() {
console.log("这是let 循环 obj 和 arr")
for (let key in {a: 1, b: 2}) {
console.log(key);
}
// a, b
for (let value of [1,2,3,4,5]) {
console.log(value);
}
// 1, 2, 3, 4, 5
}
fooLet();
function fooVar() {
console.log("这是var循环")
for (var i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0)
}
// 你可能以为会输出 0、1、2、3、4
// 实际上会输出 5、5、5、5、5
// 数据迭代保存的是最后退出的数据的值,所以在执行输出逻辑的时候保存的都是一个值
for (let i = 0;i<6;i++) {
console.log("i:",i);
}
// 1 2 3 4 5
for (const j = 0;j<6;j++) {
// j 输出0之后就报错,因为j 为常量,不可以修改这个值
console.log("j:",j);
}
}
fooVar();
</script>