基础好是你的谎言
好久之前读完了两遍红宝书第三版,所以一直洋洋得意自己基础好,
但是经过这次的字节抖音面试,真的体会到了什么是基础不好,我盲目的自信像极了人类面对三体水滴飞船时,坚信这是三体人送来的礼物一样愚蠢。
毁灭你与你何干!
痛定思痛,打算重新读一遍红宝书(第四版),并且将每天的阅读笔记记录下来,所以这是重走长征路系列的第一篇。期待我后面输出的同学可以关注一波~
文章同步在公众号:萌萌哒草头将军
let 和 var 的区别
函数作用域,可以冗余声明,变量提升
块级作用域,无法荣冗余声明,没有变量提升,但是有暂时性死区
作用域的区别
块级作用域仅仅在代码块里起作用,例如:
if (true) {
let age = 10;
console.log(age) // 10
}
console.log(age) // 语法错误
但是换做var则可以访问。
if (true) {
var age = 10;
console.log(age) // 10
}
console.log(age) // 10
函数作用域仅仅在函数内部起作用,函数外部无法访问,如果换做let也无法访问,因为函数也是个代码块。
function add () {
var age = 10
}
console.log(age) // 语法错误
变量提升和暂时性死区
变量提升:指变量声明之前可以访问变量的行为
console.log(name) // undefined
var name = "mmdctjj"
暂时性死区:变量声明之前无法访问的行为
onsole.log(name) // 语法错误
let name = "mmdctjj"
冗余声明
可以冗余声明的情况
var name = "萌萌哒草头将军"
var name = "mmdctjj"
无法冗余声明
let name = "萌萌哒草头将军"
let name = "mmdctjj" // 语法错误:name已经声明了
而且这种报错不会因为混用受影响
var name = "萌萌哒草头将军"
let name = "mmdctjj" // 语法错误:name已经声明了
let name = "萌萌哒草头将军"
var name = "mmdctjj" // 语法错误:name已经声明了
但是在不同代码块之间可以重复声明
// 仅做代码演示,不建议这么声明变量
if (local === "zn-Ch") {
let name = "萌萌哒草头将军"
} else {
let name = "mmdctjj"
}
全局声明的一些差异
var会将变量挂载到window对象上
var name = "mmdctjj"
window.name === name // true
但是let则不会
let name = "mmdctjj"
window.name // undefined
另外,如果省略声明变量的关键字,那么默认会使用var声明,也就是说
people = "a"
window.people === people // true
局部声明的一些差异
在函数中使用var声明一个变量,在执行函数后,该变量会保存在window对象上
function test() {
myName = "mmdctjj"
}
test()
myName // "mmdctjj"
window.myName // "mmdctjj"
let依然不会。造成这种差异的原因:变量提升
for循环中的一些差异
var在循环时会将变量溢出到外部
for (var i = 0; i < 5; i ++) {}
console.log(i) // 5
let则不会
for (let i = 0; i < 5; i ++) {}
console.log(i) // 语法错误:i未定义
另外会导致超出预期的行为
for (var i = 0; i < 5; i ++) {
setTimeout(() => console.log(i), 0)
}
// 预期:0,1,2,3,4
// 实际:5,5,5,5,5
```可能
但是`let`不会
```js
for (let i = 0; i < 5; i ++) {
setTimeout(() => console.log(i), 0)
}
// 实际:0,1,2,3,4
const 使用
基本的使用差异
const 和 let十分相似,不同的是,const声明变量时必须对值进行初始化赋值,且值无法被修改。
const name; // 语法错误: Missing initializer in const declaration
const people = "mmdctjj"
const people = "萌萌哒草头将军" // 语法错误
const age = 18
people = "萌萌哒草头将军" // 语法错误
age = 19 // 语法错误
我们知道变量保存基本变量类型时,只保存值,所以当用const声明一个基本类型,意味着无法被修改。
如果值为引用类型,也不能修改变量的引用地址。所以下面的修改都会报错
const people = {}
people = {} // 语法错误
但是当值为引用类型时,我们可以修改引用类型内部的属性
const people = {
name: "mmdctjj";
}
people.name = "萌萌哒草头将军";
无法在修改值的for循环中使用
for (const i = 0; i < 5; i ++) {}
// TypeError: Assignment to constant variable.
但是如果不修改值的情况,则可以使用
let i = 5
for (const j = 7; i < 5; i ++) {
console.log(j)
}
// 7, 7, 7, 7, 7
这是因为迭代变量会自增。
在
for循环中,迭代变量通常是一个数字计数器,通过自增操作来访问下一个元素。而在其他循环结构(如for...of和forEach)中,迭代变量会自动获得下一个元素,无需显式自增。
可以在for of for in中使用
for (let key in {a: 1, b: 2}) {
console.log(key)
}
// "a", "b"
for (let value of [1, 2]) {
console.log(value)
}
// 1, 2
这是因为for of for in会为每个变量声明新的变量,而不是重新赋值。
使用风格推荐
能不用var就不用var,能用const就用const,不需要修改的常量使用const,需要修改的变量使用let
最后
文章很多细节都是来自于红宝书,一些地方可能加入自己的理解,希望不会带来误解,有错误地方欢迎指正。
想要一起学习的小伙伴可以看这里