清淨
  • Java

    • Java 基础
  • 框架

    • Flyway
    • MapStruct
    • Spring Cloud
  • 中间件

    • Elasticsearch
    • Redis
    • RabbitMQ
    • Kafka
  • 三剑客

    • HTML
    • CSS
    • JavaScript
  • 进阶

    • jQuery
    • ECMAScript6
    • TypeScript
  • Vue

    • Vue2
    • Vue3
    • VuePress
  • Linux
  • Jenkins
  • Maven
  • MySQL
  • 插件工具
  • 代码集成
  • 其它

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • 设计模式
迁移日志
订阅号
微信订阅号
微信订阅号
GitHub
  • Java

    • Java 基础
  • 框架

    • Flyway
    • MapStruct
    • Spring Cloud
  • 中间件

    • Elasticsearch
    • Redis
    • RabbitMQ
    • Kafka
  • 三剑客

    • HTML
    • CSS
    • JavaScript
  • 进阶

    • jQuery
    • ECMAScript6
    • TypeScript
  • Vue

    • Vue2
    • Vue3
    • VuePress
  • Linux
  • Jenkins
  • Maven
  • MySQL
  • 插件工具
  • 代码集成
  • 其它

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • 设计模式
迁移日志
订阅号
微信订阅号
微信订阅号
GitHub
  • JavaScript

    • 简介
    • 数据类型
    • 基本语法
    • 对象
    • 函数
    • 作用域
    • this
    • 垃圾回收
    • 数组
    • 字符串
    • 正则表达式
    • DOM API
    • BOM
    • 定时器
    • 执行上下文
    • 闭包

作用域

全局作用域

直接编写在 <script></script> 中的代码就在全局作用域中。全局作用域在页面打开时创建,页面关闭时销毁。全局作用域中有一个全局对象 window(Window 对象),该对象由浏览器创建。

全局对象 window

console.log(window);

我们所创建的所有全局变量、函数等都被放在了 window 对象中。

var a = 10;
console.log(a);
console.log(window.a);
console.log(window.c); // undefined
console.log(d); // 报错,没有定义; 此时不等价于 window.d

function fun() {
  console.log(1);
}
window.fun();
window.alert(123);

变量声明提前

也称为变量提升。在 JS 执行时,所有变量的 声明(只是变量的声明,如果在声明时赋了初值,则不会带上初值)都会被提前。此方式只是针对通过 var 声明的变量。

  • 通过 var 声明

    console.log(a); // undefined
    var a = 10;
    
    // 等价代码如下
    var a;
    console.log(a);
    a = 10;
    
  • 没有通过 var 声明

    console.log(a); // 报错
    a = 10;
    console.log(window.a); // 10
    

    但是,此方式中的 a 仍是一个全局变量,并且可以通过 window 对象访问。

函数声明提前

也称为函数提前。JS 在执行时,会将所有函数的 声明 提前。

  • 函数声明的方式

    此方式会将函数的声明提前,并且函数可以被调用。

    fun();
    function fun() {
      // ...
    }
    
  • 函数表达式

    此方式只是将函数的声明提前(变量声明提前之后),但是不可提前调用。

    fun(); // 报错
    console.log(fun); // undefined
    var fun = function() {
      // ...
    }
    
    // 等价代码如下
    var fun;
    fun(); // 报错,因为 fun 不是一个函数对象
    console.log(fun); // undefined
    fun = function() {
      // ...
    }
    

函数作用域

小贴士

函数作用域也称为局部作用域。

函数作用域在调用时创建,函数被执行完成后销毁。每调用一次函数都会创建一个新的函数作用域,各自之间相互独立。在函数中也遵守全局中的某些特点,如变量声明提前,函数声明提前。因此,函数也可以被看做成一个小的全局。

  • 示例1

    var a = 20;
    function fun() {
      console.log(a); // 10,即 window.a
    }
    
  • 示例2

    function fun() {
      console.log(a); // undefined
      var a = 10;
    }
    
    // 等价代码如下
    function fun() {
      var a;
      console.log(a);
      a = 10;
    }
    
  • 示例3

    var a = 30;
    function fun() {
      var a = 10;
      function b() {
        console.log(a); // 10
        console.log(window.a); // 30
      }
      b();
    }
    
  • 示例4

    var a = 10;
    function fun() {
      console.log(a); // undefined
      var a = 30;
    }
    fun();
    
  • 示例5

    function fun() {
      d = 10; // window.d = 10
    }
    fun();
    console.log(d); // 10
    
  • 示例6

    var a = 10;
    function fun(a) {
      console.log(a);
    }
    fun(); // undefined
    fun(11); // 11
    
  • 示例7

    var a = 10;
    function fun(a) {
      console.log(a);
      a = 99; // 将传入的 a 变为了 99,并没有改变全局
    }
    fun(); // undefined
    console.log(a); // 10
    
  • 示例8

    var x = 10;
    function fu() {
      console.log(x);
    }
    function f(fu) {
      var x = 20;
      fu()
    }
    
    f(fu); // 输出 10,fu 被定义时,它的作用域就确定了
    
  • 示例9

    var fn = function () {
      console.log(fn);
    }
    fn() // 输出该函数的主体
    var obj = {
      f2: function () {
      console.log(f2);
      }
    }
    obj.f2() // 报错,f2 未定义; 此处要注意变量名 f2
    var obj = {
      f2: function () {
      console.log(this.f2);
      }
    }
    obj.f2() // 输出 f2 函数
    

注意事项

ES5 中只有全局作用域和函数作用域,没有块(即大括号)作用域。

console.log(a)// undefined
if (true) {
  var a = 10
}
console.log(a) // 10
// 上面的代码中,a 被定义在了 if 这个语句块(即大括号)中
// 但是 a 还是被当成了全局变量,并且把 a 的声明提前了,等价代码如下: 
var a
console.log(a)
if (true) {
  a = 10
}
console.log(a)

/*-------------------------------------*/
function f() {
  console.log(a)
  if (true) {
    var a = 10
  }
  console.log(a)
}
f() // 打印结果和上面的代码相同,原理也相同,等价于: 
function f() {
  var a
  console.log(a)
  if (true) {
    a = 10
  }
  console.log(a)
}

/* for 循环也是这样 */

只要是未在函数中定义的变量,都属于全局变量(前提是使用 var 定义)。

想要编辑此页?
上次更新: 2025/6/4 23:16
贡献者: Junfeng Dai
←函数this→
[ 纸上得来终觉浅绝知此事要躬行 ]
Copyright © 2021-present Junfeng Dai
蜀ICP备2021009537号