javascript IOS 上的 Safari 生成“ReferenceError: Can't find variable:”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11021576/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 11:50:12  来源:igfitidea点击:

Safari on IOS generates "ReferenceError: Can't find variable:"

javascriptiossafari

提问by Mark1270287

The following code is working correctly for all browsers including Safari on Mac, with the exception of Safari on the iPhone.

以下代码适用于所有浏览器,包括 Mac 上的 Safari,iPhone 上的 Safari 除外。

I have a timer Object that could potentially be running that is defined like so:

我有一个可能正在运行的计时器对象,其定义如下:

//delay background change until animation is finished
lastTimer = setTimeout(function () {
  $('#' + targetDiv).removeClass('open');
}, 150);

Later, I need to check if the timer is running, and if so cancel it. Here is the code I am using:

稍后,我需要检查计时器是否正在运行,如果是,则取消它。这是我正在使用的代码:

if (lastTimer != null) { clearTimeout(lastTimer); }

This is where IOS Safari generates the JavaScript Error:

这是 IOS Safari 生成 JavaScript 错误的地方:

"ReferenceError: Can't find variable: lastTimer".

“参考错误:找不到变量:lastTimer”。

Any ideas on why the check for null is not preventing the error, like it seems to with the other browsers?

关于为什么检查 null 没有阻止错误的任何想法,就像其他浏览器一样?

Here is the full code for the two pertaining functions in answer to the reply below: (edited with solution)

这是回答以下回复的两个相关函数的完整代码:(使用解决方案编辑)

// Class for handling the animations for the drop down menus
var dropDownMenu = {
lastTimer: null,
openMenu: function (targetDiv) {
    if (targetDiv != null) {
        var targetHeight = $('#' + targetDiv).height();
        $('#' + targetDiv).stop(true); //stop an previous animations and clear queue
        if (this.lastTimer != null) { clearTimeout(this.lastTimer); } //stop possible pending timer to prevent background change
        console.log("testing b");
        $('#mainNavigation #dropDownMenu ul').removeClass('open'); // make sure all closed menus show corrent bgd
        $('#' + targetDiv).animate({
            bottom: -(targetHeight + 30)
        }, 200, 'swing');
        $('#' + targetDiv).addClass('open');
    }

},
closeMenu: function (targetDiv) {
    if (targetDiv != null) {
        $('#' + targetDiv).stop(true); //stop an previous animations and clear queue
        $('#' + targetDiv).animate({
            bottom: 0
        }, 200, 'swing');
        //delay background change until animation is finished
        this.lastTimer = setTimeout(function () {
            $('#' + targetDiv).removeClass('open');
        }, 150);
    }
}
}

When the error happens in ios the execution stops and my test console.log immediately after does not execute.

当错误发生在 ios 中时,执行停止并且我的测试 console.log 不会立即执行。

采纳答案by epascarello

Your issue seems to be that on IOS, the openMenuis being invoked first.

您的问题似乎是在 IOS 上,openMenu首先调用了 。

This means that you're trying to get the value of an undeclared variable, resulting in the ReferenceError.

这意味着您正在尝试获取未声明变量的值,从而导致ReferenceError.

Oddly, you can assignto an undeclared variable, which implicitly makes it global. So if closeMenuis called first, then the assignment happens first, making the variable implicitly declared.

奇怪的是,您可以分配给未声明的变量,这隐式地使其成为全局变量。因此,如果closeMenu首先调用,则首先进行赋值,从而隐式声明变量。

The proper solution is to always declare variables before using them.

正确的解决方案是在使用变量之前始终声明它们。

var lastTimer;

But as it turned out, you preferred to use a property on the current object instead of a variable. As such, the solution was to access the property in the methods...

但事实证明,您更喜欢在当前对象上使用属性而不是变量。因此,解决方案是访问方法中的属性...

this.lastTimer

This will never throw a ReferenceError, even if the property is not declared.

ReferenceError即使未声明该属性,这也永远不会抛出 a 。

回答by sciritai

I want to chime in on this to explain. Mobile Safari is less forgiving when checking for undefined using the simple check,

我想插嘴解释一下。在使用简单检查检查未定义时,移动 Safari 不太宽容,

if variable

When you come across situations like this then use,

当您遇到这样的情况时,请使用,

if typeof variable === "undefined"

Attaching the variable to "this" is one solution here but it's just taking advantage of the fact that definedVariable.undefinedProperty returns undefined, whereas referencing an undefined variable directly will cause the reference error in some runtime environments.

将变量附加到“this”是这里的一种解决方案,但它只是利用了 definedVariable.undefinedProperty 返回 undefined 的事实,而直接引用 undefined 变量将导致某些运行时环境中的引用错误。

I would advise not getting into the habit of attaching to "this" if it's not necessary.

如果没有必要,我建议不要养成附加到“这个”的习惯。

回答by scunliffe

There's one other potential issue that I think needs to be stated. Safari on iOS* can be very aggressive on caching and not reloading a clean copy of your code.

我认为还有一个潜在的问题需要说明。iOS* 上的 Safari 在缓存和不重新加载代码的干净副本方面可能非常积极。

e.g. if you executed one version of your code without the variable defined, then fixed the code but the error continues to show on reloading (even if you close the browser/reboot the phone)

例如,如果您在没有定义变量的情况下执行了一个版本的代码,然后修复了代码,但重新加载时错误仍会继续显示(即使您关闭浏览器/重新启动手机)

To solve this, tap and hold (aka Long Press) the reload icon in the address bar and a menu pops up with 2 options Request Desktop Siteand Reload Without Content Blockers. Choosing either one of these causes a Realreload of all of the content... which resolves the issue with any cached buggy code.

要解决此问题,请点击并按住(又名长按)地址栏中的重新加载图标,然后会弹出一个菜单,其中包含 2 个选项请求桌面站点重新加载无内容拦截器。选择其中之一会导致所有内容的真正重新加载......这解决了任何缓存错误代码的问题。

*Not just Safari. Chrome on iOS (which is built on Apple's version of WebKit) can exhibit the same issue.

*不仅仅是Safari。iOS 上的 Chrome(基于 Apple 的 WebKit 版本)可能会出现同样的问题。

回答by AlexNikonov

In my case Safari 13 didnt work with ES6 consthence i needed to replace it with var

就我而言,Safari 13 不能与 ES6 一起使用,const因此我需要将其替换为var

回答by epascarello

You have a global variable in your code. Not declaring var makes it global.

您的代码中有一个全局变量。不声明 var 使其成为全球性的。

Try changing:

尝试改变:

if (lastTimer != null)

to

if (typeof lastTimer !=="undefined" && lastTimer)

if you are sticking with it being global.

如果你坚持它是全球性的。