【问题标题】:Get incremental variables live value out of a function?从函数中获取增量变量的实时值?
【发布时间】:2014-04-15 00:04:29
【问题描述】:

我一直对此感到困惑,我什至不确定这是否可能,但无论如何我都去了。

如果我有一个函数可以增加存储在变量中的值,我如何在函数之外获取变量?

例如,这不是很好的代码,但我只是在玩。

function scrollVal() {
    var pos = 0;
    $(document).scroll(function() {
        pos = $(document).scrollTop();
        return pos;
    });
}
var scrollPos = scrollVal();
console.log(scrollPos);

在这样的事情失败后我尝试了上述方法

var pos = 0;
$(document).scroll(function() {
    pos = $(document).scrollTop();
});
console.log(pos);

我不明白如何神奇地更新变量。不过必须有办法。我正在尝试使用该变量来操作元素。例

var geometry = new FSS.Plane(1600, 835, pos, 15);

所以我的问题基本上是如何在函数内动态更改一个数字,然后在函数外使用它,以便我可以操纵具有变化值的元素?

编辑提醒:我这个问题措辞不当,我的意思是它失败了,我无法在函数范围之外获得函数范围内的值。当滚动发生在实例中时,我想传递增量值。

想象您在页面上滚动,当您滚动时,某些东西会增长,或者颜色会发生变化。我认为这应该很容易,这让我听起来像个菜鸟,但我从来没有这样做过,我不确定这里适用什么规则,我理解为什么变量不更新,但我不知道解决方案。

也许无法更新实例中的值,但首先我需要获取该变量以实时呈现适当的数字,然后我才能找到。

一个很好的基本示例是将变量附加到一个元素并观察该数字随着页面的滚动而增长。我以前见过这个,所以我知道这是可能的,如果你能想到的话,这就是我喜欢代码的地方,很可能它是可能的,但是这个解决方案不是直截了当的,有一个警告!!! :)

如果我做类似的事情,这可能会成为可能

var window.pos = 0;
$(document).scroll(function() {
    pos = $(document).scrollTop();
        $('.something').html(pos);
});

显然,这是通过在函数内部实现的,但由于我需要将它传递给一个实例,我不想一遍又一遍地执行它..

【问题讨论】:

  • 你的第二个,在回调应该起作用之前声明var pos。但是您在更改它之前,在定义它之后立即通过console.log() 检查该值。如果将console.log(pos) 放在scroll() 回调中,您将看到更新后的值。同样,如果您在滚动后从浏览器控制台console.log(pos),则该值应该已更改。
  • 好的,谢谢,这是有道理的,我想我到处都是。让我尝试测试变量的主要原因是它没有在实例var geometry = new FSS.Plane(1600, 835, pos, 15); 中工作,所以我尝试使用控制台记录变量以查看它是否在递增,但实际上并没有。所以我认为这就是为什么它不能在实例中工作
  • 对不起,我想我们在这里沟通有误。我将承担大部分责任,因为我的问题措辞不佳。我可能会重新打开一个新的。我正在尝试将变量传递给构造函数,以便当我滚动实例中的元素(平面着色器)时,可以在页面滚动时实时操作。
  • 所以变量会随着页面滚动而递增,从 0 开始,然后 (0,1,2,3,4,5,6,7,8) 向上而不调用点击函数手动更新它。我让它看起来像是一个范围问题,显然不是上面的问题,但事实并非如此。这是一个实时获取价值的问题,我应该在函数之外说
  • 这完全是关于范围(变量的可用性),还是传递给FSS.plane 构造函数的整数实际上是按值传递的问题,因为它是 JavaScript 中的整数?另外,我不明白“调用点击函数”是什么意思(在上面您最近的评论中):如果您有某种更新 FSS.plane 实例的方法,请在您的 scroll 事件处理程序中使用它,其中它将以与在 click 事件处理程序中相同的方式处理。

标签: javascript variables


【解决方案1】:

我知道您可以向函数添加方法,以使它们在函数之外可用。
这是一个例子。

Fiddle 小提琴由于某种原因无法正常工作。 (我知道我应该在学校加入乐队!)

而且增量部分很简单。

(Your Variable)++;

(Your Variable)+1;

【讨论】:

  • 除了这并不真正适合我的需要。我明白了这个概念,我的问题是在函数之外获取一个值并实时获取结果。这种逻辑没有意义,但必须有一种方法:)
  • 大声笑,我明白了,如果我不快睡着,我会笑的,我睡得太久了。当我醒来时我会重新考虑它并轻笑:)
【解决方案2】:

有关在全局范围内设置值的示例,请参阅此 fiddle

更新:

要查看实时更新的示例,请参阅此fiddle。基本上,唯一的区别是每当滚动发生时值都会更新,但仍在函数之外以显示范围。

注意var theTop = 0; 是如何在全局范围内设置的,并且在每次移动滚动条时都会更新。单击按钮时,它会更新为最新值。 Javascript代码是:

var theTop = 0;
function positionMiddle()
{
    var $highlighted = $('.highlighted');    
    $highlighted.css({        
        left: ($(window).width() - $highlighted.outerWidth())/2,
        top: $(window).scrollTop() + ($(window).height() - $highlighted.outerHeight())/2
    });
    theTop = $highlighted.css('top');    
}

$(window).resize(function(){
   positionMiddle();
});

$(window).scroll(function(){    
   positionMiddle();
});

$('#currentPosButton').click(function(){    
    $('.currentTop').text(theTop);
});

// To initially run the function:
positionMiddle(); 

现在,至于你的方法对谁不起作用:

function scrollVal() {
    var pos = 0;
    $(document).scroll(function() {
        pos = $(document).scrollTop();
        return pos;
    });
}
var scrollPos = scrollVal();
console.log(scrollPos);

首先,从滚动返回 pos 是不正确的。当您从处理程序返回一个值时,它是一个布尔值,指示事件是否应该传播。但是,主要的问题是 pos 将被设置在滚动函数中,但这与 scrollVal() 的结果无关。

第二个例子:

var pos = 0;
$(document).scroll(function() {
    pos = $(document).scrollTop();
});
console.log(pos);

这更接近了,但仍然不太正确。 pos 将在滚动发生时设置,但您会在任何滚动完成之前立即记录。如果您在计时器间隔上进行日志记录,您会看到 pos 的值在您滚动时发生变化。您想阅读以了解更多的术语是scopeclosure。请参阅herehere

【讨论】:

  • 感谢您的努力,我应该更清楚,但我正在寻找价值的实时更新。我正在寻找一个例子。所以当你滚动数字更新时。
【解决方案3】:

我之前误解了你的问题。我将再次尝试回答它。我将只使用 JS 而不是我假设的 jQuery 来演示。

tl;dr - Javascript 通过值传递事物,但对象始终是引用。因此,您只需查看其引用而不是值的副本即可获得“实时更新”效果。 Here's some more detail.

我认为你想要的是这样的:

function scrollVal() {
  var res = {
    pos : 0
  };

  setTimeout(function() {
    res.pos = 10;
    return res.pos;
  }, 2000);

  return res;
}

var results = scrollVal();
console.warn(results.pos); // This could still be 0 at this point since our first setTimeout handler may have not run

setTimeout(function() {
  console.warn(results.pos); // Assuming this is executed after the first setTimeout, we should see a value of "10" printed
}, 2500);

可能不是完全您正在寻找的东西。这种精心设置的原因是 Javascript 按值而不是按引用传递结果。这意味着在执行后立即从您的函数版本返回该值的精确副本。你再也不会看到这个“实时更新”了,因为你有一个本地副本,而不是对它的引用。

然而,要意识到一个对象总是被引用(意思是一个指向内存中某个点的东西)。这意味着您将获得实际引用的副本,而不是对象的深层副本。因此,当您引用此对象时,您将在其内存位置查找它,并且由于我们在初始超时函数中对其进行了修改,因此它似乎已“实时更新”。

编辑 需要指出的另一件事是,您在指定场景中使用pos 的代码可能只是在寻找具有数字类型的值。它不适用于对象,也不会理解它已被更新。真正实现这种行为的唯一方法是在检测到位置已更改时(例如在滚动事件处理程序中)更新存储在geometry 中的对象。

【讨论】:

    【解决方案4】:

    试试这个:

      var pos = 0;
      function scrollVal() {
        pos=0;
        $(document).scroll(function() {
          pos = $(document).scrollTop();    
       });
       return pos;
     }
    var scrollPos = scrollVal();
    console.log(scrollPos);
    

    这可能会对你有所帮助。

    【讨论】:

      【解决方案5】:

      我想知道你写的关于这段代码的“类似这样的失败”是什么意思:

      var pos = 0;
      $(document).scroll(function() {
          pos = $(document).scrollTop();
      });
      console.log(pos);
      

      该代码将在控制台上记录 0,因为它 (1) 声明了一个变量 pos,(2) 将其值设置为 0,(3) 为文档的滚动事件分配了一个处理程序,并且然后 (4) 记录pos 的值。每当您滚动时,事件处理程序都会触发并更新pos 的值。但是你还没有告诉它做任何事情。让我们告诉它记录pos 的新值:

      var pos = 0;
      $(document).scroll(function() {
          pos = $(document).scrollTop();
          console.log(pos);
      });
      

      现在,当scroll 事件被触发时,您可以更改pos 的值,并查看它的记录。

      附录 1:

      您在下面的评论中询问pos“是否仍应在函数外工作”,即pos 在函数外是否可用?答案是pos 在其范围内可用。比如

      function fun() {
          var pos = 0;
          $(document).scroll(function() {
              pos = $(document).scrollTop();
          });
      }
      alert(pos); // alerts 'undefined' (assuming you've not got another `pos` within this scope)
      

      鉴于:

      function fun() {
          var pos = 0;
          alert(pos);
          $(document).scroll(function() {
              pos = $(document).scrollTop();
          });
      }
      fun(); // alerts '0'
      

      同样:

      function fun() {
          var pos = 0;
          function bun() {
              alert(pos);
          }
          bun();
      }
      fun(); // alerts '0'
      

      但我怀疑这对你有多大帮助。也许阅读此内容对您更有用: http://web.archive.org/web/20080209105120/http://blog.morrisjohns.com/javascript_closures_for_dummies 我希望你喜欢掌握 JavaScript 中的变量作用域,它并不复杂,但在开始时可能会很棘手。

      附录 2:

      听起来您的问题可能与引用/值的区别有关。在 JavaScript 中,整数(和其他原语,例如布尔值)实际上是通过值而不是引用传递的。听起来您可能希望通过更新 pos 的值对您的 FSS.plane 实例产生一些影响。本附录旨在说明为什么不会发生这种情况,并说明原则上它是如何发生的。

      所以假设我们有以下内容:

      function Rectangle(x1, y1, x2, y2) {
          this.render = function() {
              // This would draw the plane, but for illustration we'll just use:
              alert(y1)
          }
      }
      
      function updatePos() {
          pos = $(document).scrollTop()
      }
      
      var pos = 0
      
      var r = new Rectangle(0, pos, 0, 100)
      
      // 'Render' the rectangle, every second
      setTimeout(r.render, 1000)
      
      // Update the value of pos according to scroll position
      $(window).on('scroll', updatePos)
      

      这将每分钟提醒0 60 次。这是因为尽管pos 发生了变化,但在r 内部,我们将y1 评估为0:值0 已传递给构造函数。

      如果我们有

      // This time the constructor accepts two objects
      function Rectangle(coord1, coord2) {
          this.render = function() {
              alert(coord1.y)
          }
      }
      
      function Coordinate(x, y) {
          this.x = x
          this.y = y
      }
      
      var point1 = new Coordinate(0, 100)
      var point2 = new Coordinate(0, 100)
      
      // Brief and not entirely unrelated intermezzo:
      //   Notice that although 0 === 0 and 100 === 100
      //   Still new point1 != point2
      
      function updatePos() {
          point1.y = $(document).scrollTop()
      }
      
      var r = new Rectangle(point1, point2)
      
      // The next two bits stay the same:
      
      // 'Render' the rectangle, every second
      setTimeout(r.render, 1000)
      
      // Update the value of pos according to scroll position
      $(window).on('scroll', updatePos)
      

      这一次,如果用户向下滚动,每分钟 60 次的消息将会改变。

      以下将表现出相同的行为,而不会与任何构造函数混淆。

      function Rectangle(x1, y1, x2, y2) {
          this.render = function() {
              alert(y1)
          }
          // New method, a setter for y1
          this.setY1(newValue) = function {
              y1 = newValue
          }
      }
      
      var r = new Rectangle(0, 0, 0, 100)
      
      // We update the Rectangle instance directly
      function updatePos() {
          r.setY1($(document).scrollTop())
      }
      
      setTimeout(r.render, 1000)
      $(window).on('scroll', updatePos)
      

      【讨论】:

      • 它只返回 0。所以pos 还应该在函数之外工作吗?我可能会尝试将其附加到元素以查看数字增加。我认为它可能无法正常工作,因为我将它传递给实例 var geometry = new FSS.Plane(1600, 835, pos, 15);
      • “当然”不是解释。答案应说明问题发生的原因以及解决方案解决问题的原因。
      • 之所以只返回0是因为pos的值只有在传递给scroll()的回调函数被调用时才会更新。在调用回调之前,pos的初始值为0。当然pos会在函数外工作,因为它是在全局范围内声明的。
      • "它只是返回 0",你的意思是 0 被记录到控制台?在这种情况下,$(document).scrollTop() 必须是 0。是的,po 仍然会在函数之外“工作”,尽管不在其范围之外。我这里没有空间来解释,所以将用一个例子来编辑我的答案......
      • 是的,我开始看到了。但我试图找出一种方法来捕捉真正的价值,这样我就可以操纵元素。我已经看到这样做了,我认为这可能需要一些额外的东西,但我忘记了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多