1.var let const
A.var
1.如果使用var关键字定义变量,变量属于这个函数(代码块)的局部变量;
function test(){var a = 1; console.log(a)}
test();
console.log(a)
使用var定义的变量在函数作用域内有效
2.如果没有使用了var关键字定义变量,并且存在同名的全局变量,该变量等同于全局变量;
var a = 0
function test(){a = 1; console.log(a)}
console.log(a)
test();
console.log(a)
如定义 全局定义a赋值0,此时代码1答应我们全局定义的a,结果为0
我们此时运行test函数,将a赋值1,步骤2答应a=1
步骤3此时打印的仍旧是挂载在window的全局变量a,结果为1
由此可得我们test函数体内赋值的a为全局的a
3.如果使用了var关键字定义变量没有对它进行初始化,那么它是未定义并且是局部变量;
function test(){var a; console.log(a)} test(); // undefined
console.log(a) // error. 此处打印的是全局window.a
此处定义的a无法使用window.a获取到
4.定义没有使用var关键字,没有进行初始化,这个变量是一个全局变量,但是未定义的;
a; // 定义全局变量
function test(){console.log(a)} // 打印 a error 未定义
test()
console.log(a) // 打印 a error 未定义
特点:存在变量提升
var a = 1;
(function () {
console.log(a); // undefined
a = 2;
console.log(window.a); // 1
var a = 3;
console.log(window.a); // 1
console.log(a); // 3
})();
console.log(a); // 1
console.log(window.a); // 1
函数运行时形成函数作用域,var声明的会声明提前,造成里面的同一个变量为局部变量,所以在里面一切用window.打印的都为全局对象上面的对应的值
B.let
特点:块级作用域({}),无变量提升,先定义再赋值
console.log(a); let a = 1;
console.log(a); var a = 1;
for(var i = 1; i < 5; i++){
setTimeout(() => console.log(i), 0)
}
此处的i每次都会被递增的值覆盖,相当于一个全局变量,setTimeout异步执行,所以都为5
for(let i = 1; i < 5; i++){
setTimeout(() => console.log(i), 0)
}
- for( let i = 1; i< 5; i++) 这句话的圆括号之间,有一个隐藏的作用域
- for( let i = 1; i< 5; i++) { 循环体 } 在每次执行循环体之前,JS 引擎会把 i 在循环体的上下文中重新声明及初始化一次。 相当于
{let i = 1}
{let i = 2}
{let i = 3}
{let i = 4}
c.const
定义:常量是块级范围的,非常类似用 let 语句定义的变量。但常量的值是无法(通过重新赋值)改变的,也不能被重新声明。
于var 不同的是。 const定义的敞亮不会挂在到window,并且必须初始化赋值,当const的值为基本类型时,不允许修改值,当值为数组对象时可以修改其中的key和value但不允许重写整个对象
const FLAG = true
let FLAG = false
var FLAG = false
const A = [1, 2, 3, 4]
A = [1] // error
A.push(5) // A = [1, 2, 3, 4, 5]
后续会以笔记形式将es6及最新提案都整理一遍