乐趣区

关于前端:top-window-因为使用-var-遭遇的坑

明天被同学问了一个 bug,属于平时很难觉察的方面,顺便写篇文章介绍一下。

起因

明天被同学求助,帮忙看看代码有什么问题,想要实现的性能很简略,就是一个登录窗口的弹出与敞开。但遇到了 bug,窗口无奈敞开。

代码展现如下,省略了局部内容,你能发现其中的问题吗?

<div class="top"> 点击,弹出登录框 </div>
<div class="box">
  <span class="close"> 敞开 </span>
  <div class="title"> 登录 </div>
</div>
var top = document.querySelector('.top')
var box = document.querySelector('.box')
var body = document.body
var close = document.querySelector('.close')
top.addEventListener('click', function () {
  box.style.display = 'block'
  body.style.background = '#b2b2b2'
})
close.addEventListener('click', function () {
  box.style.display = 'none'
  body.style.background = ' '
})

起初我看代码感觉逻辑挺正确的,看他的测试后果事件也正确绑定了

折腾了一会,直到让他把代码发给我,亲自调试,才发现其中的猫腻

打印 top 变量,指向的居然是 window???

每次点击敞开,都因为事件冒泡,又把敞开的窗口关上了

解决办法很简略,变量改个名就行了

但这种状况我也是第一次遇见,非常诡异,就钻研了其起因

起因

说到底,这是因为 var 所导致的 bug

咱们晓得,var 申明的变量都是绑定到 window 身上,咱们应用这些变量省略 window. 的局部,然而 window 身上自带了一些变量,它们是不可改写的。

而 var 申明已有的变量,也不会报错。这就导致咱们认为申明了一个变量并正确赋了值,实际上应用的却是浏览器内置的 window 属性。

window.top 属性,返回的是窗口层级最顶层窗口的援用,是个不可改写的属性。也就导致在之前代码中申明 top 节点绑定事件,事件理论却绑定到了 window 身上。

window 身上的属性很多,高达 200 个,其中不乏咱们平时罕用的变量名,name length parent self 等。只是比拟侥幸的是,这些变量都是可写的,咱们申明它们并应用,不会引发什么谬误。

为什么又说是因为 var 导致的呢?因为如果你应用 let 定义 top 变量,会间接报错

let top = 1 // SyntaxError: Identifier 'top' has already been declared

对于那些可写的 window 属性,let 能够失常申明并赋值,不会批改 window 上的属性,应用时也是用 let 申明的变量。

解决

这种问题。不常常遇到,但真遇到了,很难排查进去。

window 属性那么多,当前还会一直新增,搞不好什么时候就遇到了。

在此提出一个解决办法:一是要回绝应用 var 只用 let const 来申明变量,二是开启 JavaScript 文件的查看性能。

在 vscode 中,能够在 setting.json 文件中设置 "js/ts.implicitProjectConfig.checkJs": true 来启用 JavaScript 文件的语义查看。

这个语义查看性能很好用,能帮你排查 js 文件中不合标准的中央,比方参数类型,变量是否已申明等等,有助于咱们养成良好的代码习惯。

结语

如果文中有谬误或不谨严的中央,请务必给予斧正,非常感激。

如果喜爱或者有所启发,心愿能点赞关注,激励一下作者。

退出移动版