const
- const声明一个
只读变量(常量),声明后不允许改变值(即栈内存的值和地址),所以const一旦声明就必须初始化
- JavaScript 的数据类型分为两类:原始值类型和对象(Object类型)
- 对于原始值类型(undefined、null、true/false、number、string),值就保存在变量指向的那个内存地址(在栈中),因此 const 声明的原始值类型变量等同于常量
- 对于对象类型(object,array,function等),变量指向的内存地址其实是保存了一个指向实际数据的指针,所以 const 只能保证指针是不可修改的,至于指针指向的数据结构是无法保证其不能被修改的(在堆中)
const x = "111";
console.log("x: ", x);
x = "111111"
const y = {
value: "222"
};
console.log("修改前y: ", y);
y.value = "333";
console.log("修改后y: ", y);
y = {}

let
- 块级作用域,在块外会被回收
- 不能重复声明
- let声明的变量在执行上下文创建阶段只会被创建,不会被初始化,因此对于执行阶段来说,如果在定义前使用则会报错,相当于使用了未被初始化的变量
for (let x = 0; x < 4; x++) {
console.log("let", x);
}
console.log("let", x);

var
- 函数作用域,作用域是全局或者整个函数快的
- 可重复声明
- 实质是在全局对象里新建了一个属性
- var声明的变量在执行上下文创建阶段会被创建并初始化,因此对于执行阶段来说,可以在声明之前使用
- 变量提升
- 由名称和对应值(undefined)组成一个变量对象的属性被创建并初始化
- 如果变量名称跟已经声明的形式参数或函数相同,则变量声明不会干扰已经存在的这类属性
console.log(a);
var a = 3;
console.log(a);
var a;
console.log(a);
a = 3;
console.log(a);
-----------------------------------------
var a = 12;
function fn() {
console.log(a);
var a = 13;
}
fn();
var a = 12;
function fn() {
var a;
console.log(a);
a = 13;
}
fn();
for (var y = 0; y < 4; y++) {
setTimeout(function () {
console.log("setTimeout y", y);
}, 1000);
console.log("var", y);
}
console.log("yyyy", y);

用var使用匿名函数实现let
for (var z = 0; z < 4; z++) {
(function f(a) {
setTimeout(function () {
console.log("var实现let", a);
}, 1000);
})(z);
}

匿名函数(function (){})()
(function (){})是标准的函数定义,没有赋值给任何变量,没有名字,也叫匿名函数。
- 匿名函数不能像普通函数那样随时随地调用,所以在匿名函数定义完后要立马调用他,后面的括号()就是运行该匿名函数。
- 类似写法还有以下
~function (){}()
-function (){}()
+function (){}()
void function (){}()
(function (){}())
(function (){})()
- 括号()前面要求必须是个表达式
~ - +符号就是把function (){}函数体转为函数表达式