You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何该闭包代码在移动版Safari浏览器中始终无法正常生效?

问题现象

除移动版Safari外,其余浏览器运行以下代码时,点击按钮可正常弹出alert提示框;但在移动版Safari环境下,代码无法正常触发alert。

const button = document.getElementById("clickme");

if (true) {
  // 将该变量移到if块外,移动版Safari下即可正常运行
  let greeting = "hello world";
  function clicked() {
    alert(greeting);
  }
  button.onclick = clicked;
}
问题原因

该问题的核心是存在bug的移动版Safari版本对块级作用域内函数声明的实现不符合ES6规范:

  • 按照ES6标准,在if、for这类块级结构中使用function关键字声明的函数,本身属于块级作用域,仅能在块内部访问,词法作用域会正确绑定当前块的上下文,可以正常捕获同块内用let/const声明的块级变量。
  • 出问题的移动版Safari会错误将块内部的函数声明提升到块外层的全局/函数作用域,这个被错误提升的clicked函数的词法上下文是外层作用域,根本无法访问if块内部用let声明的greeting变量——let声明的变量本身仅在当前块内有效,外层作用域不存在该变量,点击按钮触发函数时会直接抛出引用错误,alert自然无法执行。

如果把greeting的声明移到if块外,变量就处于外层作用域,和被错误提升的clicked函数处于同一作用域,函数可以正常访问到变量,代码就会按预期运行。

修复方案

规避这类浏览器实现差异最直接的方式,就是不在块级作用域内使用函数声明,改用函数表达式写法,从根源上避免函数被错误提升:

const button = document.getElementById("clickme");

if (true) {
  let greeting = "hello world";
  // 使用函数表达式,函数完全保留在块作用域内,不会被错误提升
  const clicked = function() {
    alert(greeting);
  };
  button.onclick = clicked;
}

也可以直接用箭头函数简写,兼容性更好:

const button = document.getElementById("clickme");

if (true) {
  let greeting = "hello world";
  button.onclick = () => alert(greeting);
}

内容的提问来源于stack exchange,提问作者argmi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 06:03:31