- 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解析