Каким образом `getService` в` injector.js` получил доступ к локальной переменной из своего вызывающего в angular?

0

Рассмотрим следующий код в официальном угловом репозитории

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;

А также

  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,
    };
  }

Мы видим, что createInternalInjector может обращаться к локальным переменным (например, path) в своей области createInjector без перехода к параметру.

Действительно, если добавить testingScope к createInjector и попытаться получить доступ в createInternalInjector, я был в состоянии сделать это.

Это странно, потому что я пытаюсь воспроизвести это поведение следующим образом.

testOuter();

function testOuter() {
  var outer = 'outer'

  testInner().test();

}

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

Но вместо этого появилась ошибка.

ReferenceError: outer is not defined

Может ли кто-нибудь дать мне несколько указаний на то, почему это происходит?

Теги:
prototypal-inheritance

1 ответ

1
Лучший ответ

Здесь речь идет о цепочке цепочки. Функция createInternalInjector вызывается в функции createInjector, поэтому она может обращаться к своим родительским свойствам. В вашем случае у вас есть функции сестры, которые не знают друг друга.

Подробнее о цепях цепей и затворах: qaru.site/questions/111232/...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню