在其es6之前的声明变量需要使用var来声明变量
var 的三个缺陷
1:全局变量挂载到全局对象(全局对象:window):全局对象成员污染问题
2:允许重复的变量声明:导致数据被覆盖
3:变量提升:怪异的数据访问、闭包问题

  1. // 全局变量挂载到全局对象:全局对象成员污染问题
  2. var abc = "123";
  3. console.log(window.abc);
  4. //污染全局对象中的console
  5. var console = "abc";
  6. console.log(console)
  7. //结果为 window.console = 123
  8. //正确的window.console = console {debug: ƒ, error: ƒ, info: ƒ, log: ƒ, warn: ƒ, …} 是一个对象
  1. //允许重复的变量声明:导致数据被覆盖
  2. var a = 1;
  3. function print(){
  4. console.log(a) // 此处输出的结果为 2
  5. }
  6. //假设这里有一千行代码
  7. var a = 2;
  8. print();
  1. //变量提升:怪异的数据访问
  2. if (Math.random() < 0.5) {
  3. var a = "abc";
  4. console.log(a);
  5. }
  6. else {
  7. console.log(a);
  8. }
  9. console.log(a); //不管if判断条件是否成立,此处输出的结果为 abc
  10. //变量提升:闭包问题
  11. var div = document.getElementById("divButtons")
  12. for (var i = 1; i <= 10; i++) {
  13. var btn = document.createElement("button");
  14. btn.innerHTML = "按钮" + i;
  15. div.appendChild(btn);
  16. btn.onclick = function () {
  17. console.log(i); //输出11
  18. }
  19. }
  20. // 循环结束后,i:11

let与const

块级作用域

块级作用域:代码执行时遇到花括号,会创建一个块级作用域,花括号结束,销毁块级作用域,在其块级作用域中声明的变量会跟着一起销毁

let

let与var的区别

let声明的变量不会挂载到全局对象
let声明的变量,不允许当前作用域范围内重复声明
使用let不会有变量提升,因此,不能在定义let变量之前使用它
在循环中,用let声明的变量会特殊处理,每进行一次循环,都会开启一个新的块级作用域,并且将循环变量绑定到该块级作用域,每次循环使用的都是一个全新的循环变量

  1. for (let i = 0; i < 10; i++) {
  2. const btn = document.createElement('button');
  3. btn.innerHTML = 'btn'+i;
  4. DIV.appendChild(btn);
  5. btn.onclick = function(e){
  6. console.log(i)
  7. }
  8. }

底层实现上,let声明的变量实际上也会有提升,但是,提升后会将其放入到“暂时性死区”,如果访问的变量位于暂时性死区,则会报错:“Cannot access ‘a’ before initialization”。当代码运行到该变量的声明语句时,会将其从暂时性死区中移除

const :常量

const和let完全相同,仅在于用const声明的变量,必须在声明时赋值,而且不可以重新赋值。
常量的不可改变是指的常量的内存空间不可改变,并不保证内存空间中的地址指向的其他空间不可变。假设是对象,对象的属性值是可以更改的,因为对象的内存空间中存储的是其属性所在内从空间的地址
常量的命名规则
1:特殊的常量:该常量从字面意义上,一定是不可变的,比如圆周率、月地距地或其他一些绝不可能变化的配置。通常,该常量的名称全部使用大写,多个单词之间用下划线分割
2: 普通的常量:使用和之前一样的命名即可
3. 在for循环中,循环变量不可以使用常量,因为常量不可被改变

**