簡體   English   中英

匿名函數中的函數范圍

[英]Function scope in anonymous functions

我剛剛配置了gulp / bower來最小化並捆綁我的JavaScript文件,並且我創建了一些遵循自執行匿名函數格式的單個JS文件。 例如,假設我有一個名為“ mobile-functions.js”的文件,其中包含一個名為“ isViewportInMobile”的函數。

mobile-functions.js

(function ($) {

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

})(jQuery);

如何從其他Javascript文件調用該函數(該文件也遵循自動執行的匿名函數格式)? 當我嘗試在其他文件中使用該函數時,它說isViewportInMobile是未定義的。

根據對相關文件的訪問量,可以對其稍加修改,以將自調用函數的范圍傳遞給變量。 但是,我假設如果您具有這樣的訪問權限,則可能不需要創建此線程,但是盡管如此,這是您可以執行的操作...

var something = (function($) {

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

    return this;
})(jQuery);

然后,您可以像這樣調用該函數:

something.isViewportInMobile(params);

我希望這是有用的。

無法直接訪問該功能,它是在另一個功能的范圍內定義的,因此對於外部世界是不可見的。 但是,有一種非常好的方法,您可以在不膨脹全局范圍通過某些全局對象訪問它們的 同時訪問該函數。

TL; DR這是可行的,可以使用匿名包裝程序和一些技巧。 無法縮短。 為文字牆做好准備。

我將嘗試舉一個示例,說明如何在不暴露全局變量的情況下如何巧妙地執行此操作,但這需要一些時間。

解釋:( 小提琴示例

上面是一個小提琴示例,我將其制作為1個小提琴,但代表了您文件的4個,我將在此處將它們作為獨立文件發布。 另外,請確保您已仔細閱讀注釋,因為其中有些行“僅顯示”有效。 在制造產品時,應將其刪除。 要測試它是否確實有效,請閱讀第113行。

這個怎么運作:
您創建的所有模塊以及放入匿名JS函數的模塊,都需要在初始化之前將其Hooks賦予使用的方法。 然后在初始化時,將鈎子捕獲到匿名函數作用域的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']--;
  })();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM