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

Safari 12.0.3无法正常设置JavaScript全局变量问题排查求助

问题原因

这是Safari 12.x版本的已知底层bug:在事件回调函数中直接修改挂载在window下的自定义对象的普通属性时,修改操作不会同步到全局上下文,回调内读取的始终是属性的初始值快照,写入操作仅在回调的局部上下文生效,不会更新全局的属性值,所以你每次点击判断MyNamespace.firstUserGesture都为true。

解决方案

方案1:使用addEventListener原生once参数(最推荐)

无需自己维护执行状态,直接通过事件绑定的配置项指定回调仅执行一次,执行后会自动移除监听器,完全规避状态读写的兼容性问题:

function doThisOnlyOnce() {
  console.log('Do stuff only once!')
}

function init() {
  const vid = document.getElementById("vid")
  vid.addEventListener('click', doThisOnlyOnce, { once: true })
}

方案2:将状态存在DOM元素的dataset属性上

Safari对DOM元素属性的读写不存在上述bug,直接把标志位存在绑定事件的元素上即可:

function doThisOnlyOnce() {
  if (this.dataset.firstUserGesture === 'true') {
    console.log('Do stuff only once!')
  }
  this.dataset.firstUserGesture = 'false'
}

function init() {
  const vid = document.getElementById("vid")
  vid.dataset.firstUserGesture = 'true'
  vid.addEventListener('click', doThisOnlyOnce)
}

方案3:用闭包封装状态,避免挂载到window

不用全局对象存状态,通过闭包把状态存在函数作用域内,规避Safari对全局对象的读写bug:

function init() {
  let firstUserGesture = true
  const vid = document.getElementById("vid")
  
  function doThisOnlyOnce() {
    if (firstUserGesture) {
      console.log('Do stuff only once!')
    }
    firstUserGesture = false
  }
  
  vid.addEventListener('click', doThisOnlyOnce)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 13:15:02