var命令
var 语句用于声明一个函数范围或者全局范围的变量,并可将其初始化为一个值。
使用
函数内部定义的变量无法在全局使用
var a =12
function fn(){
var b =15
console.log(b);
}
fn()
console.log(b); //b is not defined
函数内部可以使用全局变量
var a =12
function fn(){
console.log(a); //12
}
fn()
全局使用全局变量函数使用函数范围变量
var a =12
function fn(){
var a =15
console.log(a); //15
}
fn()
console.log(a); //12
函数内部声明全局变量
函数内省略var操作符会定义全局变量。
function fn(){
message = 'toopup'
}
fn()
console.log(message);
var全局变量会挂在window上
var a = 12
console.log(window.a); //12
声明提前
通过var 声明的变量会提升到作用域的顶部,并初始化为undefined
console.log(a); //undefined
var a = 12
function fn(){
console.log(b); //undefined
var b =15
}
fn()
js文件内使用let 或 var
test.js
var test = 12;
let testLet = 15;
index.html
<script src="./test.js"></script>
<script>
console.log(test); //12
console.log(testLet); //15
</script>
module内使用var 或 js
只在模块内部访问
test.js
var test = 12;
let testLet = 15;
export default {
}
index.html
<script type="module" src="./test.js"></script>
<script>
console.log(test); //报错 not defined
console.log(testLet); //报错 not defined
</script>
let 声明变量
通过let 声明的变量式块级作用域
let 不会声明提升
注意:
- let 声明的变量不会声明提升
- var 声明的变量会声明提升同时初始化为undefined
// ReferenceError 为 Uncaught ReferenceError: Cannot access ‘xxx’ before initialization
如下示例:
访问tmp时其未进行声明初始化操作,所以报错。
console.log(test); //undefined
console.log(tmp); // ReferenceError
var test = 15
let tmp = 16
暂时性死区
如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
即在let 命令声明变量前,变量不可用。(暂时性死区 TDZ)
if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
var 和let 混合使用
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
// tmp 没有初始化
let tmp;
}
因为我们在函数内通过let 声明tmp所以tmp只能在函数的块级作用域内访问。
不允许重复声明
let 在同一作用域内不允许重复声明同一个变量
全局作用域、块级作用域、函数作用域
var test = 15
var test = 16
console.log(test); //16
let tmp = 17
// let tmp =19 //书写时就报红
不允许在函数内部声明参数
function func(arg) {
let arg;
}
func() // 报错
const 命令
const声明一个只读的常量。一旦声明,常量的值就不能改变。
const PI = 3.1415;
PI // 3.1415
PI = 3;
// TypeError: Assignment to constant variable.
变量为引用类型
对于引用类型,其内存地址保持不变,但指向的数据结构可以发生改变。
const test =[]
test.push(1) //成功
test =[1,2,3] // TypeError: Assignment to constant variable.
不会声明提升
//ReferenceError: Cannot access 'PI' before initialization
console.log(PI);
const PI = 3.1415;
不可重复声明
const 在同一作用域内不可重复
const PI = 3.1415;
const PI = 14 //书写时就报红
函数内不可声明参数
function fn(a){
const a = 15
}
fn()
//Identifier 'a' has already been declared
注意:
let 和 var 在for循环中的问题
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
// 使用 var
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
console.log(i); //10
原因:let 是块级作用域,所以 i 只在本轮循环内有效,每一次循环的 i 都是一个新变量。
js引擎会记住上轮循环的值,在其基础上初始化本轮的变量 i
var 声明的变量在全局范围内都有效,所以共用一个 i 。所以a数组内所有方法执行的结果全是 10
const 声明迭代变量
在迭代过程中const声明的变量不能被修改
for(const i =0;i<10;i++){
console.log(i); //因为i改变了所以报错
}
// 正确格式
let obj =[1,2,3]
for(const item of obj){
console.log(item);
}
// 迭代过程中没有修改item值相当于每次循环只是用const声明变量item