Web/07-JavaScript进阶/01-var、let、const的区别.md
2021-05-18 14:53:39 +08:00

196 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## varletconst 的区别
### 1var 声明的变量会挂载在 window 对象上 let const 声明的变量不会
举例
```js
var a = '我是a';
console.log(a); // 打印结果我是a
console.log(window.a); // 打印结果我是a
```
```js
let b = '我是b';
console.log(b); // 打印结果我是b
console.log(window.b); // 打印结果undefined
```
```js
let c = '我是c';
console.log(c); // 打印结果我是c
console.log(window.b); // 打印结果undefined
```
var 的这一特性会造成 window 全局变量的污染举例如下
```js
var innerHeight = 100;
console.log(window.innerHeight); // 打印结果永远都是100 ==> 会覆盖 window 自带的 innerHeight 属性
```
### 2var 声明的变量存在变量提升let const 声明的变量不存在变量提升
举例(先使用再声明)
```js
console.log(a); // 打印结果undefined ==> a已经声明但没有赋值
var a = '我是a';
```
```js
console.log(b); // 报错Uncaught ReferenceError: Cannot access 'b' before initialization ==> 找不到b这个变量
let b = '我是b';
```
```js
console.log(c); // 报错Uncaught ReferenceError: Cannot access 'c' before initialization ==> 找不到c这个变量
const c = '我是c';
```
### 3var 声明不存在块级作用域let const 声明存在块级作用域
举例
```js
{
var a = '我是a';
let b = '我是b';
const c = '我是c';
}
console.log(a); // 我是a
console.log(b); // 报错Uncaught ReferenceError: b is not defined ==> 找不到b这个变量
console.log(c); // 报错Uncaught ReferenceError: c is not defined ==> 找不到c这个变量
```
报错是因为找不到 b c 这两个变量
### 4同一作用域下var 可以重复声明变量let const 不能重复声明变量
```js
var a = '我是a';
var a = 'qianguyihao';
console.log(a); // 打印结果qianguyihao
```
```js
let b = '我是b';
let b = 'qianguyihao';
console.log(b); //报错Uncaught SyntaxError: Identifier 'b' has already been declared ==> 变量 b 已经被声明了
```
```js
const c = '我是c';
const c = 'qianguyihao';
console.log(c); //报错Uncaught SyntaxError: Identifier 'c' has already been declared ==> 变量 c 已经被声明了
```
备注通过第3第4点可以看出使用 let/const
### 5let const 的暂时性死区DTC
**举例 1**表现正常
```js
const name = 'qianguyihao';
function foo() {
console.log(name);
}
foo(); // 执行函数后打印结果smyhvae
```
上方例子中 变量 name 被声明在函数外部此时函数内部可以直接使用
**举例 2**报错
```js
const name = 'qianguyihao';
function foo() {
console.log(name);
const name = 'hello';
}
foo(); // 执行函数后控制台报错Uncaught ReferenceError: Cannot access 'name' before initialization
```
代码解释如果在当前块级作用域中使用了变量 name并且当前块级作用域中通过 let/const **使 DTC**DTC
关于暂时性死区的更多介绍详本项目的另一篇文章JavaScript之ES6语法变量letconst和块级作用域.md
### 6const一旦声明必须赋值声明后不能再修改
一旦声明必须赋值
```js
const a;
console.log(a); // 报错Uncaught SyntaxError: Missing initializer in const declaration
```
### 总结
基于上面的种种区别我们可以知道var 声明的变量很容易造成全局污染以后我们尽量使用 let const 声明变量吧
## const 常量到底能不能被修改
我们知道 const 声明的变量无法被修改但还有一点我们一定要记住
- 如果用 const 声明基本数据类型则无法被修改
- 如果用 const 声明引用数据类型对象这里的无法被修改指的是**不能改变内存地址的引用**但对象里的内容是可以被修改的
举例 1不能修改
```js
const name = 'qianguyihao';
name = 'vae'; // 因为无法被修改所以报错Uncaught TypeError: Assignment to constant variable
```
举例 2不能修改
```js
const obj = {
name: 'qianguyihao',
age: 28,
};
obj = { name: 'vae' }; // 因为无法被修改所以报错Uncaught TypeError: Assignment to constant variable
```
举例 3可以修改
```js
const obj = {
name: 'qianguyihao',
age: 28,
};
obj.name = 'vae'; // 对象里的 name 属性可以被修改
```
因为 变量名 obj 是保存在**栈内存**中的它代表的是对象的引用地址它是基本数据类型无法被修改但是 obj 里面的内容是保存在**堆内存**中的它是引用数据类型可以被修改
**总结** const 声明的常量它所声明的
## 传值和传址的区别
详见JavaScript基础/对象简介.md
## for 循环的经典案例
详见JavaScript之ES6语法变量letconst和块级作用域.md
## 参考链接
- [JS varletconst 区别](https://juejin.im/post/5e49249be51d4526e651b654)