Рассмотрим следующий код в официальном угловом репозитории
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
Может ли кто-нибудь дать мне несколько указаний на то, почему это происходит?
Здесь речь идет о цепочке цепочки. Функция createInternalInjector
вызывается в функции createInjector
, поэтому она может обращаться к своим родительским свойствам. В вашем случае у вас есть функции сестры, которые не знают друг друга.
Подробнее о цепях цепей и затворах: qaru.site/questions/111232/...