关于JavaScript作用域你想知道的一切
什么是作用域?
在介绍作用域之前,我们先来看一下变量的定义。在JavaScript中,我们可以通过var
、let
或const
三个关键字来声明变量。
var a = 1; // 使用var声明的变量
let b = 2; // 使用let声明的变量
const c = 3; // 使用const声明的变量
那么,作用域是什么呢?
简单来说,作用域是指变量存在的环境,决定了变量的可见范围和生命周期。在JavaScript中,作用域分为全局作用域和局部作用域。
全局作用域和局部作用域
全局作用域指的是在函数外部声明的变量,它们的生命周期与页面的生命周期相同,直到页面关闭才会被销毁。
var a = 1; // 全局作用域
function test() {
console.log(a); // 1
}
test(); // 输出 1
局部作用域指的是在函数内部声明的变量,它们的生命周期只存在于当前函数内部,在函数执行完毕后会被销毁。
function test() {
var a = 1; // 局部作用域
console.log(a); // 1
}
test(); // 输出 1
console.log(a); // 报错:ReferenceError: a is not defined
作用域链
当变量在当前作用域没有找到时,会沿着作用域链向上查找。作用域链的顶端是全局作用域,当全局作用域都没有找到时,会返回undefined
。
var a = 1;
function test() {
console.log(a); // 在当前作用域找不到,向上查找,输出 1
}
test(); // 输出 1
块级作用域
在ES6之前,JavaScript中只有全局作用域和函数作用域。在函数内部使用var
声明变量,它的作用域是整个函数,而不是函数内部的块级作用域。例如:
function test() {
if (true) {
var a = 1;
}
console.log(a); // 输出 1
}
test(); // 输出 1
在ES6中,新增了let
和const
关键字,它们声明的变量具有块级作用域,只能在当前块中访问。
function test() {
if (true) {
let a = 1;
const b = 2;
}
console.log(a); // 报错:ReferenceError: a is not defined
console.log(b); // 报错:ReferenceError: b is not defined
}
test();
示例一:闭包
闭包是函数和声明该函数的词法环境的组合。闭包包含了函数和其外部的作用域。通过闭包,我们可以访问外部函数中的变量,并且外部函数执行完后,变量不会被销毁。
function outer() {
var a = 1;
function inner() {
console.log(a);
}
return inner;
}
var fn = outer();
fn(); // 输出 1
在这个例子中,inner
函数可以访问outer
函数中的a
变量,因为outer
函数的作用域被包含在inner
函数的词法环境中,而且outer
函数被执行完后,a
变量并没有被销毁,因为它被inner
函数的闭包所引用。
示例二:函数作为参数
在JavaScript中,函数也是一种数据类型,可以作为参数传递。
function add(x, y) {
return x + y;
}
function handle(fn) {
var x = 1;
var y = 2;
return fn(x, y);
}
console.log(handle(add)); // 输出 3
在这个例子中,函数add
作为参数传递给了函数handle
,并且在handle
函数内部被执行。在执行add
函数时,add
函数的作用域被包含在handle
函数的词法环境中,从而使得add
函数能够访问handle
函数内部的变量x
和y
。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:关于JavaScript作用域你想知道的一切 - Python技术站