有条件地为流行的现代浏览器定义函数的最佳方法是什么?
我看到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>
答案 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"
游戏。