简体   繁体   English

功能在Chrome中运行,但在Firefox中未运行,表示功能未定义

[英]Function runs in Chrome but doesn't run in Firefox says function not defined

This code runs perfectly in Chrome, but Firefox says the function tile1 is not defined. 该代码可以在Chrome中完美运行,但是Firefox表示未定义功能tile1 What could be the problem? 可能是什么问题呢?

Also, is there any way to shorten this function? 另外,有什么方法可以缩短此功能? I have tried using a for-loop inside tile1 and also an if-else statement but I didn't succeed. 我尝试在tile1内使用for循环以及if-else语句,但未成功。

$('div.tile').each(function(index, element) {
  for(var i=0;i<=index;i++){

  var tile1=function(){
    var one ="div.tile div.one";
    var two =" div.tile div.two";
    var three = "div.tile div.three";
    if(index==0){
      one="div.tile div.one";
      two="div.tile div.two";
      three="div.tile div.three";
    } else {
      one ="div.tile div.one"+index;
      two ="div.tile div.two"+index;
      three ="div.tile div.three"+index;
    }
      var $one=$(one);
      var $two = $(two);
      var $three=$(three);
      var oneTop = $one.top;
      var twoTop = $two.top;
      var threeTop = $three.top;
      delayRate += 3000; // delayRate 5 sec (5000) by default 

     $one
       .delay(delayRate)
       .animate({top: "-100.5%"},300,easing);   
     $two
       .delay(delayRate)
       .animate({top:"0%"},300,easing);
     $three
       .delay(delayRate)
       .animate({top:"100.5%"},300,easing);     

     $one
       .delay(12000)
       .animate({top: "-200.5%"},300,easing);
     $two
       .delay(12000)
       .animate({top:"-100.5%"},300,easing);
     $three
       .delay(12000)
       .animate({top:"0"},300,easing);

     $one
       .delay(12000)
       .animate({top: "-100.5%"},300,easing);
     $two
       .delay(12000)
       .animate({top:"0"},300,easing);
     $three
       .delay(12000)
       .animate({top:"100.5%"},300,easing);

     $one
       .delay(15000-delayRate)
       .animate({top: "0"},300,easing);
     $two
       .delay(15000-delayRate)
       .animate({top:"100.5%"},300,easing);
     $three
       .delay(15000-delayRate)
       .animate({top:"200.5%"},300,easing);

     if(i==3){
       delayRate=0;
     }
   }
 }  
 window.setInterval(tile1, 3000);
});

As I called the function the index comes randomly like 0,3,1,2, and there are 4 divs that the index corresponds to. 正如我所说的,该函数的index随机出现,如0,3,1,2,并且索引对应于4个div。

The use of function statements in JavaScript is discouraged. 不鼓励在JavaScript中使用函数语句。 Check out Mozilla's page on function scope which has a great section on function statements vs. function expressions, and states: 查阅Mozilla关于函数范围的页面,其中有很大一部分介绍了函数语句与函数表达式,并指出:

Functions can be conditionally defined using either //function statements// (an allowed extension to the ECMA-262 Edition 3 standard) or the Function constructor. 可以使用// function语句//(ECMA-262 Edition 3标准的允许扩展)或Function构造函数有条件地定义函数。 Please note that such function statements are no longer allowed in ES5 strict. 请注意,ES5 strict中不再允许此类函数语句。 Additionally, this feature does not work consistently cross-browser, so you should not rely on it. 此外,此功能无法跨浏览器一致地工作,因此您不应依赖它。

The fact that you are seeing differences between browsers with this code is not surprising. 您发现使用此代码的浏览器之间存在差异,这一事实不足为奇。

Try 尝试

var tile1 = function () {
    ...
}

While this should work for you here, it does so only because variable definitions with var are hoisted. 尽管这在这里对您有用,但这只是因为使用了var变量定义被提升了。 As JavaScript evolves and we start using let instead of var , your use of tile1 in the setInterval call outside the loop in which tile1 is defined won't work. 随着JavaScript的发展,我们开始使用let而不是var ,您tile1在定义tile1的循环之外的setInterval调用中使用tile1

One of the problems that can occur is that when you use i inside the inner function, you are always referring to the single instance of i in the outer scope (the loop counter), whose value is always equal to index . 可能出现的问题之一是,当在内部函数中使用i时, 总是在外部范围(循环计数器)中引用i的单个实例,其值始终等于index (EDIT: I show how to fix this below.) (编辑:我在下面显示了解决方法。)

Always be very, very careful when defining functions inside a loop. 在循环内定义函数时,务必非常非常小心。 You really need to understand closures and hoisting and related concepts. 您确实需要了解封闭和吊装以及相关概念。 Is there any way that tile1 can be defined globally, outside the loop? 有什么方法可以在循环外部全局定义tile1

Regarding your question on simplifying the code structure, I think you would be okay with defining tile1 with var , but I don't think you need that inner loop with i . 关于简化代码结构的问题,我认为您可以使用var定义tile1但是我认为您不需要使用i内部循环。 Try: 尝试:

 $('div.tile').each(function(index, element) { var tile1 = function () { var one ="div.tile div.one"; . . . if (index === 3) { // CHANGED I TO INDEX HERE. delayRate=0; } } window.setInterval(tile1, 3000); }); 

I'm not sure what the inner loop was buying you. 我不确定内在因素在买什么。

ASIDE: There is an effort underway for future JavaScript versions to deal with function statements in a block scope; 旁白:未来的JavaScript版本正在努力在块范围内处理函数语句。 you can see here that this is supported by certain versions of Chrome, but not Firefox. 您可以在此处看到某些Chrome版本支持此功能,但Firefox不支持。

ADDENDUM 附录

Okay now I see that you want to cycle three steps in your tile1 function. 好的,现在我看到您要在tile1函数中循环三个步骤。 While it is possible to put a for-loop inside the function, the JavaScript way is to have the function just run one step of its animation each time. 尽管可以在函数内部放置for循环,但是JavaScript的方法是使函数每次仅运行其动画的一个步骤。 If it needs some kind of counter, the counter should be external. 如果需要某种计数器,则该计数器应在外部。 One way to do this is like this: 一种方法是这样的:

var tile1 = function (i) {
  .
  .
  // use the value i here as needed
  .
  .
  setTimeout(function () {tile1((i + 1) % 3)}, 3000);
};
tile1(0);

What this does is it first calls your tile function with the value 0. Then after you do what you want at 0, you will schedule the next frame to run 3 seconds later with the i = 1. Then three seconds or so later with 2, then three seconds or so later with 0. 它的作用是首先调用值为0的tile函数。然后在0处执行所需的操作后,您将安排下一帧在i = 1的3秒后运行。然后在3秒钟后的2秒运行。 ,然后三秒钟左右的时间为0。

There is a little drift here, so you might want to use setInterval . 这里有一些漂移,因此您可能要使用setInterval This requires a closure. 这需要关闭。 The form of the solution is this: 解决方案的形式是这样的:

(function () {
  var i = 0;
  var tile1 = function () {
    .
    .
    // use the value i here as needed
    .
    .
    i = (i + 1) % 3;
  };
  setInterval(tile1, 3000);
}());

This code is pretty cool. 这段代码很酷。 It is a call of an anonymous function which calls setInterval to schedule the tile1 function to run every 3 seconds. 这是对匿名函数的调用,该函数调用setInterval来调度tile1函数每3秒运行一次。 Each time tile1 runs it uses the value of a non-local i which is hidden from the rest of the code with the closure. 每次运行tile1 ,它都使用一个非本地i的值,该值对带有闭包的其余代码是隐藏的。 Each execution of tile1 uses the right value of i , then finishes by changing i to the proper value for its next invocation! tile1每次执行tile1使用i的正确值,然后通过将i更改为其下一次调用的正确值来结束!

Both of these techniques are good to master in JavaScript. 这两种技术都可以很好地掌握JavaScript。 Have fun with them. 和他们一起玩。 The second one, of course, has no clock drift so it is probably better. 第二个当然没有时钟漂移,所以可能会更好。 To professionalize the code, you might want to assign the result of setInterval to a variable so you can call clearInterval at a later time. 为了使代码专业化,您可能希望将setInterval的结果分配给变量,以便稍后可以调用clearInterval

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM