Lazy loaded image
前端
解密 Axios:为何 axios({...}) 和 axios.get(...) 都能调用?
字数 1578阅读时长 4 分钟
2024-8-12
2025-4-28
type
status
date
slug
summary
tags
category
icon
password
引言:Axios 的两种常见用法
如果你经常和后端 API 打交道,一定对 Axios 这两种调用方式非常熟悉:
  1. 配置对象式调用: axios(config)
    1. 便捷方法调用: axios.method(url, [data], [config])
      这两种方式都能发起网络请求,非常方便。但你是否想过:
      axios 变量到底是什么?为什么它既能像函数一样直接调用 axios({...}),又能像对象一样调用 axios.post(...) 这样的方法?这背后是怎样的设计巧思?
      探究 Axios 的设计原理
      要理解这一点,我们需要深入了解 Axios 的核心构造过程。
      1. 基础:Axios 构造函数与原型方法
      从概念上讲,Axios 内部首先有一个核心的 Axios 类(构造函数),它负责管理配置(defaults)和拦截器(interceptors):
      2. 问题的出现:实例只是对象,不是函数
      按照传统的面向对象方式,我们会创建一个 Axios 的实例来使用:
      但是,我们无法直接像函数一样调用这个实例:
      这与我们平时使用的 axios({...}) 方式不符。那么,我们导入的那个 axios 究竟是如何做到既是函数又是对象的呢?
      3. Axios 的精妙之处:createInstance 工厂函数
      Axios 的开发者使用了一个非常巧妙的技巧,通过一个工厂函数 createInstance 来创建我们最终使用的 axios 对象。以下是其核心思想的简化和实际源码的结合:
      解读 createInstance 的魔法:
      • axios 首先是一个函数: 因为 instance 本身是通过 bind 创建的函数(Axios.prototype.request.bind(context)),所以你可以直接调用 axios(config)
      • axios 又是一个对象,拥有方法: 通过 Object.keys(Axios.prototype).forEach(...) 循环,get, post 等方法被直接添加为 instance 函数对象的属性。因此,你可以使用 axios.get(...), axios.post(...) 等。
      • axios 还拥有属性: 通过 Object.keys(context).forEach(...) 循环,defaults, interceptors 等实例属性也被添加为 instance 函数对象的属性,所以 axios.defaultsaxios.interceptors.request.use(...) 也能工作。
      • this 指向正确: 整个设计的关键在于 bind(context)。无论你是调用 axios(config) 还是 axios.get(...),最终执行的方法内部的 this 都被正确地指向了包含配置和拦截器的 context 实例,确保了 Axios 能正确运行。
      源码中的 this 绑定为何如此重要?
      我们看看 Axios.prototype.request 方法内部(简化示意):
      如果 request 方法在被调用时,其内部的 this 不是指向 Axios 的实例 (context),那么访问 this.defaultsthis.interceptors 就会出错。这就是为什么 createInstance 中必须使用 bind(context) 来确保 this 指向正确。
      总结
      Axios 之所以能支持 axios(config)axios.get(...) 两种调用方式,归功于其 createInstance 工厂函数的精妙设计。它返回的 axios 对象是一个“混合体”:
      1. 它本质上是一个函数 (是绑定了正确 thisAxios.prototype.request 方法)。
      1. 它又被动态地添加了 get, post 等方法属性 (同样绑定了正确的 this)。
      1. 它还被添加了 defaults, interceptors 等实例属性。
      这种设计模式,利用了 JavaScript 函数即对象的特性,创造出了一个既灵活又强大的 API 接口,堪称 JavaScript 库设计的典范。
      上一篇
      autofit.js 前端可视化大屏自适应终极解决方案
      下一篇
      【Vue2 / Vue 3】一个适配手机、平板、PC 的后台模板,开源且免费!