重新复习ES6语法知识,**参照的是阮一峰老师的 ESCMAScript6入门 es6.ruanyifeng.com/#docs/let**… 会加上一些自己的理解。不足之后,还请多多指点!
1.let命令
let和var的区分
引用
console.log(a) // Uncaught ReferenceError
console.log(b) // undefined
let a
var b
从报错上我们能看出,前者是引用错误,后者是因为可以变量提升,所以是未定义
{
let a = 1
var b = 2
}
console.log(b) // 2
console.log(a) // Uncaught ReferenceError: a is not defined
同样是因为作用域和变量提升问题,导致两个结果各不相同。
for循环
- var 声明的参数,在全局范围内使用,全局只有一个变量,每次改变,都会改变当前值,
- let 声明的参数,只在本循环中使用,每次循环的i都是一个新的变量
for(let i = 0; i < 5; i++) {
console.log(i) // 0 1 2 3 4
}
console.log(i) // Uncaught ReferenceError: i is not defined
对比var
for(var i = 0; i < 5; i++) {
console.log(i) // 0 1 2 3 4
}
console.log(i) // 5
var声明的参数提升到了全局,相比较,使用let会更好一些。
再看一个例子
var a = [];
for(var i = 0; i < 5; i++) {
a[i] = function () {
console.log(i)
}
}
a[2]() // 5
上边的代码,其实我们想输出的其实是2,但因为我们声明使用的是var,所以没有达到我们想要的结果,对比下let
let a = [];
for(let i = 0; i < 5; i++) {
a[i] = function () {
console.log(i)
}
}
a[2]() // 2
使用let,它的这种块级作用域就达到了我们的目标。
变量提升的问题
变量提升的问题,我们在最上边的例子里就有说到。这里我们了解下暂时性死区
暂时性死区
只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
大致意思是,在代码块中,使用let变量之前,当前变量都不能使用,报ReferenceError引用错误,称之为暂时性死区
如下例子
var a = 123;
if (true) {
a = 'abc'; // Uncaught ReferenceError
let a;
}
在上边的代码中,我们虽然在最上层声明了var a = 123,但在块级作用域内使用了let,就形成了一个暂时性死区。因此就报了引用类型错误。
暂时性死区 - 函数
function bar(x = y, y = 2) {
return [x, y];
}
bar(); // 报错 ReferenceError
在函数中,虽然x前也没有let或var,但是默认了var,但是在y赋值到x的过程中,y作为值,当前是没有声明的,因此报了ReferenceError的错
再看下边的例子
function bar(x = 2, y = x) {
return [x, y];
}
console.log(bar()) // [2, 2]
先声明了x并赋值,然后再声明y,并将x的值赋值给y,完美!
var a = a
let b = b // Uncaught ReferenceError
主要看赋值的a 和b
在a中,赋值的a,自动生成了var a ,但是赋值的b,此时并没有声明,整个流程应该是先拿到赋值的参数的声明,然后有值拿值,没有值就undefined,之后再去赋值
不允许重复声明
变量声明不可重复,也不能在函数内部重新声明参数。重复声明则报语法错误 SyntaxError。 如以下两种
var a
let a // SyntaxError
function a(b) {
let b
} // 报错
下面的是正确的
function c(d) {
{
let d
}
} // 不报错
块级作用域
var a = new Date();
function b() {
console.log(a) // undefined
if (false) {
var a = 'a'
}
}
b()
直接这个例子似乎有些看不懂,不明白为啥输出的是undefined 先拆开来看
var a = new Date();
function b() {
console.log(a) // Sun Aug 01 2021 22:00:25 GMT+0800 (中国标准时间)
// if (false) {
// var a = 'a'
// }
}
b()
现在我们拿到的是外层的变量
然后再改
var a = new Date();
function b() {
console.log(a) // undefined
if (true) {
var a = 'a'
}
}
b()
现在看到和true,false也无关了。 真正的原因是因为内层变量提升会覆盖外层变量。
代码如下
var a = new Date();
function b() {
var a
console.log(a) // undefined
if (true) {
a = '123'
}
}
b()
变量泄露
这个问题例子就是我们之前说到的使用var的for循环
for (var i = 0; i < 5; i++) {
console.log(i); // 0 1 2 3 4
}
console.log(i); // 5
但使用let后,我们就能修改到这个问题
如下
function c() {
let d = 5
if(true) {
let d = 10;
}
console.log(d) // 5
}
c()
块级作用域和函数声明
ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
例子如下
if (true) {
function f() {}
}
try {
function f() {}
} catch(e) {
// ...
}
function a() { console.log('Outside')}
(function(){
if(false) {
function a() { console.log('inside')}
}
a()
})() // TypeError: a is not a function
允许在块级作用域内声明函数,函数声明类似于var,即会提升到全局作用域或函数作用域的头部。同时,函数声明还会提升到所在的块级作用域的头部。
function f() { console.log('I am outside!'); }
(function () {
var f = undefined;
if (false) {
function f() { console.log('I am inside!'); }
}
f();
}());
// Uncaught TypeError: f is not a function
块级作用域内部,优先使用函数表达式
{
let a = '1';
let f = function () {
return a;
};
}
const 命令
- const声明一个只读的常量。一旦声明,常量的值就不能改变。
- 只声明不赋值,就会报错
- 只在声明所在的块级作用域内有效
- 同样存在暂时性死区,只能在声明的位置后面使用。
- 不可重复声明 以下是证明的例子
const b = {}
b.a = 'a'
b = {} // Uncaught TypeError: Assignment to constant variable.
console.log(a) // Uncaught ReferenceError
const a = 10
冻结对象只能冻结简单类型的数据如string ,number ,array
对象属性冻结
let constatize = (obj) => {
Object.freeze(obj)
Object.keys(obj).forEach((key, i) => {
if(typeof obj[key] === 'object') {
constatize(obj[key])
}
})
}
以上就是我的全部收获了,不足之处,还请多多指教!