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
相关产品推荐
相关产品推荐

