2016-08-01 9 views
0

Betrachten Sie den folgenden Code in den offiziellen angular repositoryWie hat `getService` in` injector.js` auf lokale Variable von seinem Aufrufer in angular zugegriffen?

function createInjector(modulesToLoad, strictDi) { 
    strictDi = (strictDi === true); 
    var testingScope = 'this is a test'; 
    var INSTANTIATING = {}, 
     providerSuffix = 'Provider', 
     path = [], 
     loadedModules = new HashMap([], true), 
     providerCache = { 
     $provide: { 
      provider: supportObject(provider), 
      factory: supportObject(factory), 
      service: supportObject(service), 
      value: supportObject(value), 
      constant: supportObject(constant), 
      decorator: decorator 
      } 
     }, 
     providerInjector = (providerCache.$injector = 
      createInternalInjector(providerCache, function(serviceName, caller) { 
      if (angular.isString(caller)) { 
       path.push(caller); 
      } 
      throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- ')); 
      })), 
     instanceCache = {}, 
     protoInstanceInjector = 
      createInternalInjector(instanceCache, function(serviceName, caller) { 
      var provider = providerInjector.get(serviceName + providerSuffix, caller); 
      return instanceInjector.invoke(
       provider.$get, provider, undefined, serviceName); 
      }), 
     instanceInjector = protoInstanceInjector; 

    providerCache['$injector' + providerSuffix] = { $get: valueFn(protoInstanceInjector) }; 
    var runBlocks = loadModules(modulesToLoad); 
    instanceInjector = protoInstanceInjector.get('$injector'); 
    instanceInjector.strictDi = strictDi; 
    forEach(runBlocks, function(fn) { if (fn) instanceInjector.invoke(fn); }); 

    return instanceInjector; 

Und

function createInternalInjector(cache, factory) { 

    function getService(serviceName, caller) { 
     console.log(testingScope); 
     if (cache.hasOwnProperty(serviceName)) { 
     if (cache[serviceName] === INSTANTIATING) { 
      throw $injectorMinErr('cdep', 'Circular dependency found: {0}', 
        serviceName + ' <- ' + path.join(' <- ')); 
     } 
     return cache[serviceName]; 
     } else { 
     try { 
      path.unshift(serviceName); 
      cache[serviceName] = INSTANTIATING; 
      return cache[serviceName] = factory(serviceName, caller); 
     } catch (err) { 
      if (cache[serviceName] === INSTANTIATING) { 
      delete cache[serviceName]; 
      } 
      throw err; 
     } finally { 
      path.shift(); 
     } 
     } 
    } 
    return { 
     get: getService, 
    }; 
    } 

Wir sehen, dass createInternalInjector die Lage ist, lokale Variablen (path wie) in Rahmen seines Anrufers createInjector ohne auf den Parameter im Vorbeigehen .

In der Tat, wenn ich testingScope zu createInjector hinzufügen und versuchen, in createInternalInjector zuzugreifen, konnte ich es tun.

Das ist seltsam, weil ich versuche, dieses Verhalten wie folgt zu replizieren.

testOuter(); 

function testOuter() { 
    var outer = 'outer' 

    testInner().test(); 

} 

function testInner() { 
    function testing() { 
    console.log(outer); 
    } 
    return { 
     test: testing 
    } 
} 

Aber stattdessen ein Fehler.

ReferenceError: outer is not defined 

Kann mir jemand ein paar Hinweise geben, warum das passiert?

Antwort

1

Das Problem hier ist Verkettung. createInternalInjector Funktion wird innerhalb createInjector Funktion aufgerufen, daher kann es auf seine übergeordneten Eigenschaften zugreifen. In Ihrem Fall haben Sie Geschwisterfunktionen, die sich untereinander nicht bewusst sind.

Mehr über Umfang Ketten und Verschlüsse: https://stackoverflow.com/a/1484230/5954939

Verwandte Themen