1.var,const,let

8 阅读2分钟
  • 1.var
  • 1.1 var声明提升
function foo() {
  console.log(age);
    var age = 26;
    
    
  }
foo(); //undefined,不报错,所以var声明提升,提升到了函数作用域的顶部
console.log(age) //报错:ReferenceError: age is not defined,所以var声明的范围是函数作用域
  • 1.2 var声明的范围是函数作用域,允许重复声明
if (true) { 
  var name = 'Matt';
  console.log(name); // Matt

}
console.log(name);   // Matt,代码块里的变量依旧可以访问
var name = 'Nicholas';
if (true) {
var name = 'Matt';
console.log(name);  // Matt
}
console.log(name);  // Matt,代码块修改了外层name的值
  • 1.3 var声明的全局变量,自动成为window对象的属性
 var name = 'Matt';
 console.log(window.name); // 'Matt'
  • 2.let
  • 2.1 let声明的范围是块作用域,块作用域是函数作用域的子集
if (true) {
  let age = 26;
  console.log(age);//26
}
console.log(age);// ReferenceError: age 没有定义
  • 2.2 let不允许重复声明
let age;
let age; //SyntaxError;标识符age已经声明过了
var name;
let name; // SyntaxError
  • 2.3 let声明不会提升,又名暂时性死区
console.log(age); // ReferenceError:age 没有定义
let age = 26;
  • 2.4 let声明的变量不会添加到window上
let age = 26;
console.log(window.age);  // undefined
  • 2.5 for中的var和let
for (var i = 0; i < 5; ++i) {
    setTimeout(() => console.log(i), 0)
} //输出5个5
//原因:var声明的变量会渗透到循环体外部,在退出循环时,迭代变量保存的是导致循环退出的值:5,在之后执行循环逻辑时,所有的i都是同一个变量,因而输出的都是同一个最终值

//使用闭包
 for (var i = 0; i < 5; ++i) {
      (function(i){
        setTimeout(() => console.log(i), 0)
      })(i)
  } 
// 会输出0、1、2、3、4

for (let i = 0; i < 5; ++i) {
    setTimeout(() => console.log(i), 0)
}  
// 会输出0、1、2、3、4
//原因:Javascript引擎在后台会为每个迭代循环声明一个新的迭代变量,每个setTimeout引用的都是不同的变量实例
  • 3.const
  • 3.1 const声明时必须同时初始化变量,且不能修改,其他与let一致
const age=26
age = 36 //TypeError
  • 3.2 const声明的限制只适用于它指向的变量的引用-如果const变量引用的是一个对象,修改对象内部的属性并不违反const的限制
const person = {}
person.name = 'aa'

script标签中的defer和async 1.不使用的情况下,script标签按序执行,并且会阻塞DOM解析 2.使用defer和async 2.1 相同点:不阻塞 DOM 解析,浏览器一边解析 HTML,一边在后台下载脚本文件,两者并行。 2.2 不同点:async下载后立即,无序执行,执行时阻塞DOM解析 defer下载后,DOM解析完毕再按顺序执行,全程不阻塞DOM解析