JavaScript中已初始化的变量类型是否可能为undefined?
reCAPTCHA初始化代码中grecaptcha.ready内层undefined校验的作用
这层校验是防御性的兜底兼容逻辑,和示例中外层的grecaptcha初始化代码并不冲突,存在的核心原因有三个:
grecaptcha.ready的这段垫片实现是通用逻辑,不会强依赖示例中外层的空对象初始化
官方给出的完整示例是理想状态下的接入流程,但实际开发中不可能所有开发者都逐行照搬前置代码:有人会把ready逻辑单独抽成公共工具函数复用,有人会漏写外层的grecaptcha = {}占位代码,还有人会把reCAPTCHA调用逻辑分散在页面不同脚本块里。如果删掉这层内层校验,一旦全局环境下根本没有声明grecaptcha变量,调用grecaptcha.ready时会直接抛出ReferenceError,导致后续所有脚本逻辑中断。- 利用typeof的语法特性做无副作用兜底
JS语法里,用typeof判断一个从未声明过的变量不会触发引用错误,只会返回'undefined'。只要走到grecaptcha不存在的分支,代码就会自动把传入的回调存入全局的___grecaptcha_cfg回调队列——这个队列是reCAPTCHA官方脚本约定的缓存位,等异步加载的api.js加载完成后,会自动读取队列里的所有回调按顺序执行,整个过程完全不需要依赖提前初始化的grecaptcha空对象。 - 覆盖极端加载顺序场景
就算开发者写了外层的grecaptcha初始化,也可能因为脚本注入顺序、动态加载、第三方脚本篡改全局变量等意外情况,导致执行到ready方法内部时grecaptcha被删除或重置,这层判断可以避免这类极端场景下的报错。
如果删掉这层校验,只要接入方漏写外层的grecaptcha初始化,下面这段代码就会直接中断执行:
// 漏写外层grecaptcha空对象初始化逻辑 grecaptcha.ready(function(){ grecaptcha.render("container", { sitekey: "ABC-123" }); });
有了这层校验,哪怕完全不写外层的空对象初始化,直接调用grecaptcha.ready也不会报错,回调会被正确存入队列,等官方脚本加载完成后正常执行。
内容的提问来源于stack exchange,提问作者tykatyk
相关产品推荐
相关产品推荐

