在现代浏览器中有条件地定义函数? Esp Safari?

时间:2018-10-19 17:52:21

标签: javascript google-chrome firefox google-analytics safari

有条件地为流行的现代浏览器定义函数的最佳方法是什么?

我看到Safari 12(iOS 12.0.1和macOS 10.14)错误地定义了条件函数,而Chrome,Firefox,Edge似乎做对了。此外,JS引擎的规范正确行为是什么,因此,如果是bug,我可以向Apple报告此bug。

背景:我们这样做是为了避免在用户不同意GDPR的情况下加载Google Analytics(分析)(gtag.js)。 Google的gtags.js样板初始化代码中有一行function gtag(){dataLayer.push(arguments);}使Safari跳闸。

下面的代码,演示位于JS Fiddle here

<html>
  <head>
    <title>Safari JS engine test</title>
    <script type="text/javascript">
      if (false) {
        function conditionalFunctionality() {
          alert("Doing conditional functionality");
        }
      }
      window.onload = function() {
        if (typeof conditionalFunctionality === "function") {
          alert("BAD. It's defined");
        } else {
          alert("GOOD. It's NOT defined");
        }
      }
    </script>
  </head>
  <body>
    <h1>Safari JS engine test</h1>
  </body>
</html>

面部照片

iOS macOS

2 个答案:

答案 0 :(得分:1)

正如Pointy的评论所提到的,您不想有条件地定义函数。而是要为所有浏览器定义函数,然后根据浏览器有条件地在主体中执行代码。

这篇stackoverflow帖子详细介绍了如何检测某些浏览器,因此在这里我不再重复:How to detect Safari, Chrome, IE, Firefox and Opera browser?

然后您可以编写类似的内容

function f(...) {
    if (isSafari()) {
        // Safari specific stuff
    else {
        // other stuff
    }
}

其中isSafari函数是我链接的stackoverflow帖子中的支票的包装器。

编辑:指出您希望基于特定的功能而不是浏览器。在这种情况下,您应该在上面的示例中将isSafari替换为适当的函数,以检查当前浏览器是否支持所需的功能,而不是检查浏览器的类型。

我提供的链接实际上检查了浏览器的功能,以确定正在使用的浏览器,因此您应该可以使用它来解决问题。

答案 1 :(得分:1)

如上面的注释所示,当函数定义不是“顶级”时,它们的行为可能不直观。例如:

a()
function a() { console.log("here"); }
即使功能定义在使用后出现,

也将登录到控制台。这在Javascript中称为起吊,此处提供了很好的描述:

  

https://gomakethings.com/function-expressions-vs-function-declarations/

(由pointy提供)

不同的浏览器版本执行此提升的方式有所不同,导致您观察到不一致,以及为什么“严格”模式(即,在代码块顶部使用"use strict";会更改此行为)。

当我想要获得这种行为时,我倾向于使用“函数表达式”。看起来更像这样:

var conditionalFunctionality;
if (false) {
  conditionalFunctionality = function () {
    console.log("conditionally defined");
  }
}
if (conditionalFunctionality) {
  conditionalFunctionality();
}

其优点还在于具有适当的自然“虚假”变量,并且不需要玩任何typeof conditionalFunctionality === "function"游戏。