JavaScript之作用域

作用域

作用域是指代码中定义变量的区域。即变量(变量作用域又称上下文)和函数生效(能被访问)的区域或集合

作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。换句话说,作用域决定了代码区块中变量和其他资源的可见性

举个例子:

function myFunction() {
    let inVariable = "函数内部变量";
}
myFunction();//要先执行这个函数,否则根本不知道里面是啥
console.log(inVariable); // Uncaught ReferenceError: inVariable is not defined

上述例子中,当我们在全局访问这个变量的时候,系统会报错。这就说明我们在全局是无法获取到(闭包除外)函数内部的变量。

作用域一般分成:

  • 全局作用域
  • 函数作用域
  • 块级作用域

1. 全局作用域

任何不在函数中或是大括号中声明的变量,都是在全局作用域下,全局作用域下声明的变量可以在程序的任意位置访问。

在代码的任何地方都能访问到的变量和函数处于全局作用域。当你在任何地方(不在任何函数内部)声明一个变量或函数时,它都处于全局作用域。全局变量在整个程序中都是可见的,但过度使用全局变量可能会导致命名冲突和代码难以维护。

var globalVar = 'I am a global variable';  
  
function globalFunction() {  
    console.log('I am a global function');  
}

2. 函数作用域(局部作用域)

函数作用域也叫局部作用域,如果一个变量是在函数内部声明的它就在一个函数作用域下面。这些变量只能在函数内部访问,不能在函数以外去访问,它们的作用域被限制在函数体内部。这意味着在函数外部无法直接访问函数内部声明的变量或函数,除非它们被显式地暴露为全局变量或通过某种机制(如返回值或闭包)传递到外部。

function exampleFunction() {  
    var localVar = 'I am a local variable';  
      
    function localFunction() {  
        console.log('I am a local function');  
    }  
      
    console.log(localVar); // 输出: I am a local variable  
    localFunction(); // 输出: I am a local function  
}  
  
exampleFunction();  
  
console.log(localVar); // ReferenceError: localVar is not defined     函数内部声明,只能内部访问
localFunction(); // ReferenceError: localFunction is not defined      函数内部声明,只能内部访问

可见上述代码中在函数内部声明的变量或函数,在函数外部是无法访问的,这说明在函数内部定义的变量或者方法只是函数作用域


3. 块级作用域

ES6之块级作用域

ES6引入了let和const关键字,和var关键字不同,在大括号中使用let和const声明的变量存在于块级作用域中。在大括号之外不能访问这些变量,这些变量只在声明它们的代码块(例如 if 语句、for 循环等)内部可见。这进一步增强了作用域的控制能力。

if (true) {  
    let blockScopedVar = 'I am block-scoped';  
    console.log(blockScopedVar); // 输出: I am block-scoped  
}  
console.log(blockScopedVar); // ReferenceError: blockScopedVar is not defined


{
  // 块级作用域中的变量
  let greeting = 'Hello World!';
  var lang = 'English';
  console.log(greeting); // Prints 'Hello World!'
}
console.log(lang); // 变量 'English'
console.log(greeting); // 报错:Uncaught ReferenceError: greeting is not defined

静态作用域与动态作用域

1. 静态作用域(词法作用域)

函数的作用域在函数定义的时候就确定了

具体来说,函数的作用域是由其在代码中定义的位置决定的,而不是由函数调用的位置决定。

当函数内部需要访问某个变量时,会按照从当前作用域开始,逐级向上查找,直到找到全局作用域为止的顺序进行查找。(作用域链)

JavaScript 采用词法作用域(lexical scoping),也就是静态作用域。

2. 动态作用域

函数的作用域是在函数调用的时候才确定

这意味着,函数的作用域取决于函数在何处被调用,以及调用它的上下文环境。

.

让我们认真看个例子就能明白之间的区别:

var value = 1;

function foo() {
    console.log(value);
}

function bar() {
    var value = 2;
    foo();
}

bar();

// 结果是 ???

假设JavaScript采用静态作用域,让我们分析下执行过程:
执行 foo 函数,先从 foo 函数内部查找是否有局部变量 value,如果没有,就根据书写的位置,查找上面一层的代码,也就是 value 等于 1,所以结果会打印 1。

假设JavaScript采用动态作用域,让我们分析下执行过程:
执行 foo 函数,依然是从 foo 函数内部查找是否有局部变量 value。如果没有,就从调用函数的作用域,也就是 bar 函数内部查找 value 变量,所以结果会打印 2。

前面我们已经说了,JavaScript采用的是静态作用域,所以这个例子的结果是 1。


作用域链

当在Javascript中使用一个变量的时候,首先Javascript引擎会尝试在当前作用域下去寻找该变量,如果没找到,再到它的上层作用域寻找,以此类推直到找到该变量或是已经到了全局作用域

如果在全局作用域里仍然找不到该变量,它就会在全局范围内隐式声明该变量(非严格模式下)或是直接报错

把作用域比喻成一个建筑,这份建筑代表程序中的嵌套作用域链,第一层代表当前的执行作用域,顶层代表全局作用域

在这里插入图片描述
变量的引用会顺着当前楼层进行查找,如果找不到,则会往上一层找,一旦到达顶层,查找的过程都会停止

var sex = '男';
function person() {
    var name = '张三';
    function student() {
        var age = 18;
        console.log(name); // 张三
        console.log(sex); // 男 
    }
    student();
    console.log(age); // Uncaught ReferenceError: age is not defined
}
person();
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫老板的豆

你的鼓励将是我创作的最大动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值