前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库可选链函数调用 this 绑定影响
JavaScript函数与作用域

obj.fn?.() 怎么用?用可选链调用方法,this 会丢吗?

obj.fn?.() 的意思是「fn 存在就调用,不存在就算了」。fn 是 null 或 undefined 时整个表达式返回 undefined;存在时和 obj.fn() 完全一样,this 还是 obj,不会丢。它只防 null 和 undefined,fn 是个字符串照样抛 TypeError。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#函数与作用域
先看核心答案读代码示例
理解线索

`?.` 放在哪,就保护哪一段

  1. obj?.fn()obj 是 null 或 undefined 时返回 undefined,fn 不存在照样报错
  2. obj.fn?.()fn 不存在时返回 undefined,obj 本身不存在照样报错
  3. obj?.fn?.()两段都保护,任何一段缺失都返回 undefined

返回 undefined 有两种可能:方法不存在被跳过了,或者方法存在但本来就返回 undefined。业务上要区分这两种情况时,得先单独判断方法在不在。

核心回答

先记住这个答案

可选链用于函数调用时写成 fn?.()。?. 左边的值是 null 或 undefined 时,调用被跳过,表达式直接返回 undefined,括号里的参数也不会求值;否则就正常调用。用在方法上写成 obj.fn?.(),调用时 this 仍然是 obj,和 obj.fn() 完全一样,不会因为加了 ?. 就丢失。要注意 ?. 的位置:obj?.fn() 只在 obj 缺失时短路,obj 存在但没有 fn 时还是会抛 TypeError。

  • obj.fn?.() 调用时 this 仍是 obj
  • obj?.fn() 只保护 obj,不保护 fn
  • 短路时括号里的参数不会求值
  • 只防 null 和 undefined,不防非函数值

跑一遍看 this 和短路

一个日志对象,分别调用存在的方法、不存在的方法,再把方法取出来单独调用。

方法存在、不存在、被取出来JavaScript
'use strict'
const logger = {
  prefix: 'app',
  write(msg) {
    return `${this.prefix}:${msg}`
  }
}
console.log(logger.write?.('ready')) // this 仍是 logger
console.log(logger.flush?.(console.log('参数被求值了'))) // 短路,参数不求值

const write = logger.write
try {
  write?.('ready') // 取出来再调,this 是 undefined
} catch (err) {
  console.log(err.name)
}
let config = null
console.log(config?.load()) // config 是 null,直接短路
查看输出与解释
app:ready
undefined
TypeError
undefined

第一行正常输出 app:ready,说明 this 就是 logger。第二行 flush 不存在,调用被跳过,参数里的 console.log 也没有执行,控制台里看不到「参数被求值了」。 第三段是面试官想考的点:write?.() 只能保证 write 存在,它是从对象上取下来的,前面没有 logger. 了,this 是 undefined,读 this.prefix 抛 TypeError。所以 ?. 不会帮你保住 this,也不会让丢掉的 this 回来,this 保不保得住只看调用时前面有没有对象。

为什么 ?. 不影响 this

obj.fn() 的 this 是 obj,是因为调用时引擎知道这个函数是从 obj 上取出来的。obj.fn?.() 在语法上还是一个「从 obj 上取 fn 再调用」的表达式,?. 只是在调用前多加了一步检查:fn 是不是 null 或 undefined。检查通过就按原来的方式调用,obj 这个接收者一直都在。

常见用法:可选的回调
组件和工具函数经常接收可选的回调,比如 props.onChange?.(value)、options.onSuccess?.(data)。以前要写 if (typeof onChange === 'function') onChange(value) 或者 onChange && onChange(value),现在一个 ?. 就够了。因为是通过 props. 调用的,回调里如果用了 this,拿到的是 props 对象,这一点和不加 ?. 时一样。
回答前,多想一步

容易答错的地方

以为 ?.() 能防止所有调用错误
它只在左边是 null 或 undefined 时短路。属性存在但不是函数,比如 obj.fn 是字符串,obj.fn?.() 照样抛 TypeError: obj.fn is not a function。方法内部抛出的错误也会正常往外传,?. 不会吞掉。
把 ?. 放错位置
接口数据里 user 可能为空,写成 user.getName?.() 保护不了,user 是 null 时读 getName 就报错了。要保护 user 就写 user?.getName(),两段都不确定就写 user?.getName?.()。
试着用自己的话回答

面试官还会怎么问?

a?.b.c() 在 a 是 null 时会报错吗?

不会。短路会跳过整条链后面的所有部分,.c() 也不会执行,整个表达式返回 undefined。不需要写成 a?.b?.c?.(),只在真正可能缺失的那一段加 ?. 就行。

new 能和可选链一起用吗?

不能,new Foo?.() 是语法错误。可选链也不能出现在赋值号左边,obj?.a = 1 同样是语法错误。

eval?.() 和 eval() 有什么区别?

eval(code) 是直接 eval,代码在当前作用域执行,能读写当前的局部变量。eval?.(code) 不算直接调用,变成了间接 eval,代码在全局作用域执行,读不到局部变量。这是个冷门知识点,实际项目里应该避免用 eval。

从一道题,走向一组知识

把知识连起来

函数与作用域

怎么用闭包实现私有变量?有哪几种写法?

闭包返回的方法不依赖 this,取出来用 fn?.() 调用也没问题;依赖 this 的方法取出来就会丢。

函数与作用域

什么是副作用?纯函数有什么特点,为什么要用它?

可选调用短路时连参数都不求值,参数里如果带着副作用,会跟着一起被跳过。

参考资料

  • JavaScript:函数与作用域参考资料

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 跑一遍看 this 和短路
  3. 为什么 ?. 不影响 this
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑