模块内的 JavaScript 范围问题

Javascript scope issue inside a module

本文关键字:范围 问题 JavaScript 模块      更新时间:2023-09-26

当像下面的代码中一样声明时,$sessionTimeLeftupdateSession()内访问时是未定义的。但是当我$sessionTimeLeft声明和赋值移动到initiate()内部时,我得到了正确的jQuery对象。我想当$sessionTimeLeft由于关闭而在initiate()内部声明时,我可以访问它。但是为什么$sessionTimeLeft超出了我的原始代码的范围呢?

var session = (function SessionManager() {
  var timeLeftInMs;
  var timeLeftInMin;
  var delay; // in ms
  var $sessionTimeLeft = $('#dcSessionTimeLeft');
  /* Set up the module by setting the timeout and delay time. */
  function initiate(_timeout, _delay) {
    timeLeftInMin = _timeout;
    timeLeftInMs = timeLeftInMin * 60 * 1000;    
    delay = _delay; // delay in ms      
    setInterval(updateSession, delay);
  }
  function updateSession() {
    timeLeftInMs -= delay;
    timeLeftInMin = timeLeftInMs / 60000; // convert ms to min.              
    $sessionTimeLeft.text(timeLeftInMin);
  }
  var publicAPI = {
    initiate: initiate
  };
  return publicAPI;
})();
session.initiate(30,1000);

这里的问题是,当您尝试访问#dcSessionTimeLeft时,它可能尚未加载。因此,确保加载它的一种方法是将代码包装在document.ready中:

$(function() {
  var session = (function SessionManager() {
  var timeLeftInMs;
  var timeLeftInMin;
  var delay; // in ms
  var $sessionTimeLeft = $('#dcSessionTimeLeft');
  /* Set up the module by setting the timeout and delay time. */
  function initiate(_timeout, _delay) {
    timeLeftInMin = _timeout;
    timeLeftInMs = timeLeftInMin * 60 * 1000;    
    delay = _delay; // delay in ms      
    setInterval(updateSession, delay);
  }
  function updateSession() {
    timeLeftInMs -= delay;
    timeLeftInMin = timeLeftInMs / 60000; // convert ms to min.              
    $sessionTimeLeft.text(timeLeftInMin);
  }
  var publicAPI = {
    initiate: initiate
  };
  return publicAPI;
  })();
  session.initiate(30,1000);
});

在这种情况下,闭包也应该绝对有效。此代码不起作用的原因是您没有正确调用会话函数。请记住,此函数返回一个带有函数启动的对象

代码的最后一行应该是

session.initiate(30,1000);

这应该有效。为了重现问题,我使用了节点。我将 $sessionTimeLeft 变量更改为字符串 hello 并测试它是否仍然可以在 updateSession 函数中访问。我的代码是

var session = (function SessionManager() {
  var timeLeftInMs;
  var timeLeftInMin;
  var delay; // in ms
  var $sessionTimeLeft = "Hello";
  /* Set up the module by setting the timeout and delay time. */
  function initiate(_timeout, _delay) {
    timeLeftInMin = _timeout;
    timeLeftInMs = timeLeftInMin * 60 * 1000;
    delay = _delay; // delay in ms
    setInterval(updateSession, delay);
  }
  function updateSession() {
    timeLeftInMs -= delay;
    timeLeftInMin = timeLeftInMs / 60000; // convert ms to min.
    console.log($sessionTimeLeft);
  }
  var publicAPI = {
    initiate: initiate
  };
  return publicAPI;
})();
session.initiate(30,1000);

我得到的结果是

Hello
Hello
Hello
Hello
Hello

每 1 秒一次。