在THIS文章中,我不理解以下陈述:
请注意,内部函数不能调用外部函数 但是,参数对象,即使它可以调用外部 函数的参数直接。
有人可以帮助我理解提到的两点
答案 0 :(得分:7)
理解这两个陈述的关键是:
了解arguments
是什么
了解“影子”
那么让我们谈谈arguments
,然后谈谈阴影,然后我认为这两个陈述试图说的是相当清楚的。
arguments
arguments
对象作为函数范围的一部分提供:它实际上是一个自动定义的变量,它具有调用函数的参数的伪数组:
function foo() {
console.log("My arg count: " + arguments.length);
}
foo(1, 2, 3); // My arg count: 3
当我说自动定义时,我的意思是,就像你有这个:
// CONCEPTUAL, not real
function foo() {
var arguments = /*...magic code to get the arguments we were called with */;
console.log("My arg count: " + arguments.length);
}
foo(1, 2, 3); // My arg count: 3
...这只是JavaScript引擎为你做的。
arguments
对象很像一个数组 - 如上所述,它有length
,您可以使用通常的[]
表示法访问各个参数:
function foo() {
var n;
console.log("My arg count: " + arguments.length);
for (n = 0; n < arguments.length; ++n) {
console.log(arguments[n]);
}
}
foo(1, 2, 3);
输出:
My arg count: 3 1 2 3
您甚至可以在同一个函数中使用命名参数和arguments
伪数组:
function foo(a) {
console.log("a = " + a);
console.log("arguments[0] = " + arguments[0]);
}
foo("Hi there");
输出:
a = Hi there arguments[0] = Hi there
这是一个伪数组,因为虽然它有length
和[]
索引,但它的不是实际上是一个数组,并不是全部正常数组具有的功能(如slice
,forEach
等)。
在松散模式下,它还具有非常令人惊讶的属性,它链接到命名参数,所以你得到这样奇怪的东西:
function foo(a) {
console.log("before: a = " + a);
arguments[0] = a * 2;
console.log("after: a = " + a);
}
foo(10);
输出:
befer: a = 10 after: a = 20幽灵,嗯?在严格模式下,该链接不存在(因为引擎执行此操作的成本很高)。
好的,那就是arguments
。什么是“阴影”的事情?
函数为变量创建“范围”,并且存在于其中,因为您可以在其他函数中包含函数,所以可以在范围内包含范围。其他函数内的函数可以访问包含它们的作用域,因此:
function outer() {
var a = 10;
// `a` exists here
function inner() {
var b = 20;
// both `a` and `b` exist here
console.log("a = " + a + ", b = " + b);
}
// only `a` exists here
inner();
}
a
存在于outer
范围内,inner
可以访问。 b
仅存在于inner
。
只要我们使用不同的名称,那就没关系,但假设我们使用了a
:
function outer() {
var a = 10;
// `a` exists here
function inner() {
var a = 20;
// `a` exists here -- but which one is it?
console.log("a = " + a);
}
inner();
}
由于inner
有自己的a
变量,因此无法再访问outer
的{{1}} - a
{{1} 阴影(隐藏)inner
的{{1}}。
对于变量,命名参数,在范围内创建的函数,以及在范围内赋予名称含义的任何内容都是如此。
那么阴影与这两个陈述有什么关系呢?我们来看看......
“呼叫”在这里是错误的词; “访问”会更有意义。
请记住上面的概念示例,其中a
基本上是一个自动声明的变量?
outer
现在您已了解阴影,您可能会看到它的发展方向。这段代码:
a
显示
Outer arg count: 3 Inner arg count: 0
...因为在arguments
内,// CONCEPTUAL, not real
function foo() {
var arguments = /*...magic code to get the arguments we were called with */;
console.log("My arg count: " + arguments.length);
}
foo(1, 2, 3); // My arg count: 3
指的是内部函数的function outer() {
function inner() {
console.log("Inner arg count: " + arguments.length);
}
console.log("Outer arg count: " + arguments.length);
inner();
}
outer(1, 2, 3);
对象,而不是外部函数。这就像他们都声明了一个同名的局部变量:inner
阴影中的变量(隐藏)arguments
中的变量。
现在,“内部函数无法调用外部函数的参数对象”并非如此。内部函数可以访问外部函数的arguments
对象,但不能访问该名称 - 如果inner
将其分配给变量,则没有问题:
outer
显示
Outer arg count: 3 Outer's arg count from inner: 3
此声明不完整:arguments
可以访问outer
的参数提供function outer() {
var outerArgs = arguments;
function inner() {
console.log("Outer's arg count from inner: " + outerArgs.length);
}
console.log("Outer arg count: " + arguments.length);
inner();
}
outer(1, 2, 3);
不会影响他们。所以这很好:
inner
输出:
Outer's a = 10
...但是在这里,outer
被遮蔽,因此inner
只能看到自己的function outer(a) {
function inner() {
console.log("Outer's a = " + a);
}
inner();
}
outer(10);
,而不是a
:
inner
输出:
a = undefined
所以,两个陈述都是关于范围和阴影的。
答案 1 :(得分:3)
在每个函数的主体中,有一个特殊的类数组对象,名为arguments
,它包含调用函数的所有实际参数。例如:
function f() {
console.log(arguments);
}
f('one', 2, 3.0);
大多数语言都要求您声明这些参数,但JavaScript并不关心您使用的参数数量。
由于在任何给定时间(最多)范围内只有一个arguments
变量,因此您无法从封闭函数访问arguments
变量:
function f() {
function g() {
console.log(arguments); // will log ['blue'], not ['red']
}
g('blue');
}
f('red');
答案 2 :(得分:1)
- 内部函数不能调用外部函数的参数对象
醇>
如果你有
function outer(){
function inner(){
doSomething(arguments);
}
}
然后arguments
引用直接包含该行的函数的参数。所以inner
的论点。你无法从那里得到outer
的论据。
- 内部函数可以直接调用外部函数的参数。
醇>
function outer(a,b,c){
function inner(d,e,f){
doSomething(a,b,c);
}
}
只要保持参数(和局部变量)名称不同,您仍然可以从outer
内部访问inner
的参数(这里是a
,{{ 1}}和b
)。