匿名函数中的函数范围

时间:2016-07-15 13:09:40

标签: javascript jquery

我刚配置gulp / bower来缩小和缩小捆绑我的javascript文件,我创建了一些遵循自执行匿名函数格式的单个JS文件。例如假设我有一个名为“mobile-functions.js”的文件,其中包含一个名为“isViewportInMobile”的函数。

移动-functions.js

(function ($) {

    function isViewportInMobile(mobileWidthOverride) {
        var widthToCheckAgainst = mobileWidthOverride || 768;
        return window.innerWidth < widthToCheckAgainst;
    }

})(jQuery);

如何从不同的Javascript文件(也遵循自动执行的匿名函数格式)调用该函数?当我尝试在我的其他文件中使用该函数时,它表示isViewportInMobile未定义。

2 个答案:

答案 0 :(得分:1)

根据您对相关文件的访问权限,您可以稍微修改它以将自调用函数的范围传递给变量。但是,我假设如果你有这样的访问权限,你可能不需要创建这个帖子,但是你可以做到这一点......

something.isViewportInMobile(params);

然后,这将允许您像这样调用函数:

$lines = file('file.txt'); // this will open file and split them into lines
$items = array();
foreach($lines as $line){
   $name = null;
   $number = null;
   $nameFound = preg_match("|([A-Za-z]+)|", $line, $matches);
   if($nameFound){
      $name = $matches[0];
   }
   $numberFound = preg_match("|([0-9]+)|", $line, $matches);
   if($numberFound){
      $number = $matches[0];
   }

   $items[] = array('name' => $name, 'number' => $number);
}

我希望这有一些用处。

答案 1 :(得分:0)

无法直接访问该功能,它在另一个功能的范围内定义,因此对外界不可见。但是,有一种非常好的方法可以访问功能,同时不会使全局范围膨胀通过某个全局对象访问它们

TL; DR 这是可行的,有匿名包装和一些技巧。不能缩短。坚持自己的文字墙。

我将尝试举例说明如何在不暴露全局变量的情况下巧妙地做到这一点,但是需要一些时间。

消耗:fiddle Example

上面是一个小提琴示例,我作为一个小提琴,但代表您的4个文件,我将它们作为分隔文件发布在这里。另外,请务必仔细阅读评论,因为有一些线条只是要显示&#39;有用。在制作产品时应将其取下。要测试它真的有效,请阅读第113行。

工作原理:
您创建的所有模块以及匿名JS函数都需要在初始化之前将它们的Hook用于您使用的方法。然后在初始化时,钩子被捕获在匿名函数范围的this对象中供您使用。

模块的模式非常简单,您需要具备以下条件:

  (function() {
    var wrapper = this;
    function InitializeModule(hookObject) {
      var hooks = Object.keys(hookObject);
      var i;
      for (i = 0; i < hooks.length; i++) {
        wrapper[hooks[i]] = hookObject[hooks[i]];
      }
      delete window['methodRegistrationName-config.js'];
    }
        //MAKE YOUR FUNCTIONS BELOW
    //------------------------------------------------------------------


    //------------------------------------------------------------------
    function InitializeHooks(hooksObject) {
        //REGISTER YOUR FUNCTIONS LIKE THIS:
      hooksObject.addHook('globalyUniqueID', functionName)

      window['methodRegistrationName-config.js'] = InitializeModule;
    }
    window['methodRegistrationName-config.js'] = InitializeHooks;
    window['activeModules']--;
  })();

所有模块都遵循完全相同的模式,您可以自由地制作和引用在任何其他模块中创建的任何函数(假设它已加载)。您需要做的就是制作我在下面指定的config.js和fileHandler.js,并根据需要添加任意数量的模块。所有配置都在config.js中完成。

我已经制作了两个模块(module1.js和module4.js)并将它们发布在下面,这样你就可以看到它的工作原理。查看开头链接的小提琴。

像这样制作 config.js

//CONFIG.js
(function() {
  //User manually configures which modules he wants to use
  var config = {
    // Name : [ load? , path, methodRegistrationName ]
    Module1: [true, 'js/module1.js', 'InitializeModule1'],
    Modele2: [false, 'js/module2.js', 'InitializeModule2'],
    Module3: [false, 'js/module3.js', 'InitializeModule3'],
    Module4: [true, 'js/module4.js', 'InitializeModule4']
  }

  Initialize();
  //-------------------------
  //   DO NOT TOUCH BELOW (a note for your users)
  //-------------------------
  function Initialize() {
    //Required module to make all of this work (this one always has to be added);
    config['fileHandler'] = [true, 'js/filehandler.js'];
    //-----------------------------------------------------------------------------
    var modules = Object.keys(config);
    var activeModules = 0;
    var i;
    var bodyElement = document.getElementsByTagName('body')[0];
    var scriptString = "";
    for (i = 0; i < modules.length; i++) {
      if (config[modules[i]][0]) {
        scriptString = "<script type=\"text/javascript\" scr=\"" + config[modules[i]][1] + "\">";
        // Now this next line is going to be commented because we dont want fiddle to use it,
        // instead we will alert. In your project however you want to add these and NOT alert.
        // bodyElement.innerHTML += scriptString;
        activeModules++;
        console.log(scriptString);
        //These scripts will be added to the body;
      }
    }

    window['activeModules'] = activeModules;
    var interval = setInterval(scriptsLoadedCheck, 500)

    function scriptsLoadedCheck() {
      if (window['activeModules'] === 0) {
        //all scripts loaded, clear interval you are ready to continue
        clearInterval(interval);
        delete window['activeModules'];
        InitializeFileHandler(config);
      }
    }
  }
})();

现在使 fileHandler.js 像这样(这是唯一一个无法包装,但它可以与config合并,在这种情况下它被包装):

//FILEHANDLER.js
function InitializeFileHandler(configObject) {
  var moduleHooks = {
    addHook: function(id, callback) {
      if (this.checkHook)
        moduleHooks[id] = callback;
      else
        console.error("Hook already registered.")
    },
    checkHook: function(id) {
      if (this[id] !== undefined)
        return true;
      return false;
    }
  }

  initializeActiveModules();

  function initializeActiveModules() {
    var modules = Object.keys(configObject);
    var i;
    for (i = 0; i < modules.length; i++) {
      if (modules[i] === 'fileHandler')
        continue;
      if (configObject[modules[i]][0]) {
        console.log(configObject[modules[i]]);
        window[configObject[modules[i]][2]](moduleHooks);
      }
    }
    //------------------------------------------------------------HOOKS INITIALIZED, NOW REAL
    for (i = 0; i < modules.length; i++) {
      if (modules[i] === 'fileHandler')
        continue;
      if (configObject[modules[i]][0]) {
        window[configObject[modules[i]][2]](moduleHooks);
      }
    }
  }
}

window['activeModules']--;

现在您可以制作模块,例如 module1.js

  //MODULE1.js
  (function() {
    var wrapper = this;

    function InitializeModule(hookObject) {
      var hooks = Object.keys(hookObject);
      var i;
      for (i = 0; i < hooks.length; i++) {
        wrapper[hooks[i]] = hookObject[hooks[i]];
      }
      delete window['InitializeModule1'];
      //This next line should NOT be here, it is here just to test/show it works
      Module1Function1();
    }

    function Module1Function1() {
        //Change the arguement to 'Module4Function1ID' to simulate a call from Module4;
      console.log(Module1Function2ID());
    }

    function Module1Function2() {
      return "Worked!";
    }

    function InitializeHooks(hooksObject) {
      hooksObject.addHook('Module1Function1ID', Module1Function1)
      hooksObject.addHook('Module1Function2ID', Module1Function2)

      //Once hooks are initialized, the initialization process switches to the module
      window['InitializeModule1'] = InitializeModule;
    }
    window['InitializeModule1'] = InitializeHooks;
    window['activeModules']--;
  })();

,例如 module4.js ,如下所示:

 //MODULE4.js
  (function() {
    var wrapper = this;

    function InitializeModule(hookObject) {
      var hooks = Object.keys(hookObject);
      var i;
      for (i = 0; i < hooks.length; i++) {
        wrapper[hooks[i]] = hookObject[hooks[i]];
      }
      delete window['InitializeModule4'];
    }

    function Module4Function1() {
      return "Function from module4";
    }

    function InitializeHooks(hooksObject) {
      hooksObject.addHook('Module4Function1ID', Module4Function1)

      //Once hooks are initialized, the initialization process switches to the module
      window['InitializeModule4'] = InitializeModule;
    }
    window['InitializeModule4'] = InitializeHooks;
    window['activeModules']--;
  })();