Chrome 61.0.3163.79 中的冲突 Javascript 变量名

Conflicting Javascript variable name in Chrome 61.0.3163.79

我的 Chrome 浏览器最近已更新到版本 61.0.3163.79,我注意到以下 Javascript 代码有一个奇怪的行为:

<!doctype html>
<html lang="fr">
    <head>
        <script>
            var scroll = {
                myFunction : function() {console.log('myFunction called');}
            }
        
            scroll.myFunction(); /* first call */
            window.scroll.myFunction(); /* second call */
        </script>
    </head>
    <body>
        <button onclick="scroll.myFunction()">test1</button> <!-- third call -->
        <button onclick="window.scroll.myFunction()">test2</button> <!-- fourth call -->
    </body>
</html>

此代码覆盖了 window.scroll 函数(不要问我为什么,那是遗留代码)。 运行 以及单击 "test1" 和 "test2" 按钮时,控制台中的结果如下:

myFunction called
myFunction called
Uncaught TypeError: scroll.myFunction is not a function at HTMLButtonElement.onclick
myFunction called

在早期的 Chrome 版本和 MSIE 11 中,单击 "test1" 和 "test2" 按钮时函数调用正常工作,导致控制台中出现以下消息:

myFunction called
myFunction called
myFunction called
myFunction called

现在问题:

请注意,在此期间,我更改了变量名称以避免名称与浏览器本机功能冲突。

<button onclick="scroll.myFunction()">test1</button>

这里的问题是你之后的滚动条在 window 对象上,

它会出现在 Chrome 的最新版本中,他们已经向实际按钮添加了滚动方法。所以你最终调用的是 button.scroll.myFunction,而不是 window.scroll.myFunction.

浏览器供应商可以随时添加任何命名方法,因此即使您创建了一个名为 myScroll 的全局方法,理论上也没有什么可以阻止浏览器供应商向按钮元素添加 myScroll。显然他们不太可能这样做,但需要注意一些事情。

避免此类问题的最佳方法是始终控制您的范围,永远不要依赖全局变量,除非将这些全局变量传递到范围中。 Javascript 闭包在这里真的很有帮助。不幸的是,在您的示例中,您使用了 HTML 事件绑定,而不是代码绑定,因此无法实现。