0. 标识符
就是变量、函数、属性或函数参数的名称。标识符可以由一或多个下列字符组成:
- 第一个字符必须是一个字母、下划线(_)或美元符号($);
- 剩下的其他字符可以是字母、下划线、美元符号或数字。
3个关键字可以声明变量:var、const和let。
其中,var 在 ECMAScript 的所有版本中都可以使用,而 const 和 let 只能在 ECMAScript 6 及更晚的版本中使用。
1. var
1.1 var 定义的变量的作用域是函数作用域
var message = "hello"
console.log(message) // "hello"
function sayHi(){
var gretting = "hi";
console.log(gretting);
}
sayHi() // "hi"
console.log(gretting); // Uncaught ReferenceError: gretting is not defined
从上面的例子可以看到 使用 var 定义的变量具有函数作用域
假如我们在上面的函数里面定义变量的时候不使用 var ,那么我们来看看会怎么样?
function sayHi(){
gretting = "hi";
console.log(gretting);
}
sayHi() // "hi"
console.log(gretting); // undefined
为什么会这样,因为不使用关键字,而是直接去声明的变量会成为全局对象 window 下面的属性
console.log(window.gretting) // undefined
1.2 var 声明的变量具有声明提升。
console.log(fruit) // undefined
var fruit = "apple";
为什么会输出 undefined,而不是Uncaught ReferenceError
因为 var 声明的变量具有声明提升。这段代码的真正执行顺序是:
var fruit;
console.log(fruit);
fruit = "apple";
2. let
使用 let 声明变量的方式是从 ES6 之后有的。
2.1 使用 let 声明的变量的作用域是块级作用域
if(true){
let phone = "iPhone11";
console.log(phone) // "iPhone"
}
console.log(phone); // ReferenceError
2.2 使用 let 定义的变量不能重复定义
let name;
let name; // SyntaxError;标识符age已经声明过了
2.3 let 没有声明提升
console.log(age); // ReferenceError
let age = 10;
2.4 使用 let 声明的变量不会成为 window 的属性
let a = 10
console.log(window.a) // undefined
2.5 for 循环中的 let 声明
我们先来看一段代码:
for(var i = 0;i<5;i++){
}
console.log(i) // 5
for(let i = 0;i<5;i++){
}
console.log(i) // ReferenceError
for(var i = 0;i<5;i++){
setTimeout(()=>{console.log(i)})
}
// 5 5 5 5 5
for(let i = 0;i<5;i++){
setTimeout(()=>{console.log(i)})
}
// 0 1 2 3 4
为什么会这样?
JavaScript引擎在后台会为每个迭代循环声明一个新的迭代变量。每个 setTimeout 引用的都是不同的变量实例
3.const
const 声明和 let 声明的作用差不多。具有差别的是 const 声明的时候必须赋值,并且使用 const 声明的变量不能进行修改
3.1 const 声明的时候必须赋值
const a
const a // SyntaxError
3.2 const 声明的变量不能进行修改
const b =10
b =1 // TypeError
3.3 使用 const 声明的对象,可以修改它的属性,但是不能将其指向一个新的指针
const obj = {
name: "tim"
}
obj.name = "jerry"
console.log(obj.name) // jerry
obj = {}
console.log(obj) // TypeError