目录
变量作用域
- var:函数作用域,具有变量提升
- let:块级作用域,不具有变量提升
- const:块级作用域,不具有变量提升
注意:“尽管var、let、const具备不同的作用域,但它们都依赖于所处的环境。如果var、let、const在同一函数内部的顶部声明,那么三者具备相同的作用域”
function simple(){
var x = 1;
let y = 2;
const z = 3;
console.log(x, y, z); // 1 2 3
}
- 上面三者在顶部声明,所处环境都是simple()函数内,因此具备相同的作用域
var
var声明的变量具备函数作用域,也就是在函数内部声明的变量,在函数外部无法访问,在函数内部,该变量都可以被访问
甚至在声明之前也可访问(变量提升)
function simple(){
if (true){
var x = 1;
}
console.log(x); //1
}
function simple2(){
var x = 2;
console.log(x); //2
}
console.log(x); //ReferenceError: x is not defined
- 在simple函数中,使用var声明了变量x,x拥有函数作用域,所以在if语句中声明的x,在外部仍然可以访问
- 在函数外部访问x时,会报错,因为x仅在函数内部有效
console.log(x); //undefined
var x = 1;
console.log(x); //1
上面代码使用了“变量提升”,它允许在变量声明之前就使用该变量。
- 在JavaScript中,当代码执行前,js引擎会对var声明的变量和function声明的函数进行预解析,即:var和function会被提升到当前作用域的顶部,但是赋值操作不会被提升
- 在上面代码中,var x = 1;这行代码实际上分为两个步骤:声明变量x和给x赋值
- 由于变量提升,var x会被提升到当前作用域顶部,所以在console.log(x)时,变量x已经被声明,但未被赋值,因此输出undefined
let
let
声明的变量具有块级作用域,这意味着在块级作用域(如 if
语句块、for
循环、while
循环等)内声明的变量,仅在该块级作用域内可访问。
function simple(){
if (true){
let x = 1;
}
console.log(x); //ReferenceError: x is not defined
}
function simple2(){
let x = 2;
console.log(x); //2
}
console.log(x); //ReferenceError: x is not defined
- 在if语句块中声明的变量y,所以仅能在if语句块内部可以访问
const
const
声明的常量同样具有块级作用域,和let
类似,在块级作用域内声明的常量,仅在该块级作用域内可访问。并且,一旦使用const
声明常量,就必须同时进行初始化,之后无法再重新赋值。
function simple(){
if (true){
const x = 1;
}
console.log(x); //ReferenceError: x is not defined
}
function simple2(){
const x = 2;
console.log(x); //2
}
console.log(x); //ReferenceError: x is not defined
- 在if语句块中声明的变量y,所以仅能在if语句块内部可以访问
在script中
- 在HTML中,<script>的执行是顺序执行,即有多个<script>标签,那么会从上往下执行
- <script>的作用域是全局作用域,即在<script>中声明的变量,都是全局作用域
- 所有的<script>共享一个全局作用域
<script>
var x = 1;
let y = 2;
const z = 3;
</script>
<script>
console.log(x); // 1
console.log(y); // 2
console.log(z); // 3
</script>
- 上面代码的声明和使用虽然不在一个<script>内,但是由于所有的<script>共享一个作用域,因此可以正确调用
外部引用JS文件
引用的js文件和HTML中<script>标签内的作用域共享一个全局环境
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 在HTML中的<script>标签内定义全局变量
var globalVar1 = '我是HTML中定义的全局变量';
function globalFunc1() {
console.log('我是HTML中定义的全局函数');
}
</script>
<script src="./test.js"></script>
<script>
// 调用外部JS文件的函数
console.log(globalVar2)
globalFunc2();
</script>
</body>
</html>
test.js:
// test.js文件内容
console.log(globalVar1); // 可以访问HTML中定义的全局变量
globalFunc1(); // 可以调用HTML中定义的全局函数
// 在外部JS文件中定义全局变量和函数
var globalVar2 = '我是外部JS文件中定义的全局变量';
function globalFunc2() {
console.log('我是外部JS文件中定义的全局函数');
}
效果:
在标签中使用内联js
在HTML标签内部使用内联形式的JavaScript代码,其作用域就是全局作用域
与全局作用域共享变量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Inline JS Scope</title>
</head>
<body>
<button onclick="console.log(globalVar);">点击查看全局变量</button>
<script>
// 定义全局变量
var globalVar = 'Hello, Global!';
</script>
</body>
</html>
内联代码创建的变量将在全局作用域下
如果内联 JavaScript 代码创建了新的变量,这些变量会成为内联变量(作用域仅在内联代码中使用)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Inline JS Scope</title>
</head>
<body>
<button onclick="var localVar = 'Hello, Local!'; consoleLog();">点击创建变量</button>
<script>
function consoleLog() {
console.log(localVar); //ReferenceError: localVar is not defined
}
</script>
</body>
</html>