And*_*897 4 javascript closures
在此文章中,我不明白下面的语句:
注意,内部函数不能调用外部函数的arguments对象,但是,即使它可以直接调用外部函数的参数.
有人可以帮我理解上面提到的两点
理解这两个陈述的关键是:
了解什么arguments是
理解"阴影"
那么让我们谈谈arguments,然后讨论阴影,然后我认为这两个陈述试图说的是相当清楚的.
arguments该arguments对象作为函数中作用域的一部分提供:它实际上是一个自动定义的变量,它具有调用函数的参数的伪数组:
function foo() {
console.log("My arg count: " + arguments.length);
}
foo(1, 2, 3); // My arg count: 3
Run Code Online (Sandbox Code Playgroud)
当我说自动定义时,我的意思是它非常像你有这个:
// 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
Run Code Online (Sandbox Code Playgroud)
...这只是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);
Run Code Online (Sandbox Code Playgroud)
输出:
My arg count: 3 1 2 3
您甚至可以arguments在同一函数中使用命名参数和伪数组:
function foo(a) {
console.log("a = " + a);
console.log("arguments[0] = " + arguments[0]);
}
foo("Hi there");
Run Code Online (Sandbox Code Playgroud)
输出:
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);
Run Code Online (Sandbox Code Playgroud)
输出:
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();
}
Run Code Online (Sandbox Code Playgroud)
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();
}
Run Code Online (Sandbox Code Playgroud)
在那里,因为inner有自己的a变量,它不能访问outer的a了- inner的a 阴影(隐藏)outer的a.
对于变量,命名参数,在范围内创建的函数,以及在范围内赋予名称含义的任何内容,都是如此.
那么阴影与这两个陈述有什么关系呢?我们来看看......
"呼叫"在这里是错误的词; "访问"会更有意义.
还记得我们上面的概念示例,其中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
Run Code Online (Sandbox Code Playgroud)
现在您已了解阴影,您可能会看到它的发展方向.这段代码:
function outer() {
function inner() {
console.log("Inner arg count: " + arguments.length);
}
console.log("Outer arg count: " + arguments.length);
inner();
}
outer(1, 2, 3);
Run Code Online (Sandbox Code Playgroud)
节目
Outer arg count: 3 Inner arg count: 0
...因为在里面inner,arguments指的arguments是内部函数的对象,而不是外部函数.它就像它们都声明了一个具有相同名称的局部变量:inner 阴影中的变量(隐藏)中的变量outer.
现在,"内部函数不能调用外部函数的参数对象"并不是真的.内部函数可以访问外部函数的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);
Run Code Online (Sandbox Code Playgroud)
节目
Outer arg count: 3 Outer's arg count from inner: 3
这个陈述是不完整的:提供的inner访问outer参数不会影响它们.所以这很好:inner
function outer(a) {
function inner() {
console.log("Outer's a = " + a);
}
inner();
}
outer(10);
Run Code Online (Sandbox Code Playgroud)
输出:
Outer's a = 10
......但是在这里,a被遮蔽,所以inner只看到自己的a,而不是outer:
function outer(a) { // <== declares a named argument `a`
function inner(a) { // <== ALSO declares a named argument `a`
console.log("a = " + a);
}
inner();
}
outer(10);
Run Code Online (Sandbox Code Playgroud)
输出:
a = undefined
实际上,这两个陈述都只涉及范围和阴影.
在每个函数的主体中,都有一个特殊的类似数组的对象,arguments它包含调用函数时使用的所有实际参数。例如:
function f() {
console.log(arguments);
}
f('one', 2, 3.0);
Run Code Online (Sandbox Code Playgroud)
大多数语言会要求您声明这些参数,但 JavaScript 并不关心您使用了多少个参数。
由于在任何给定时间(最多)范围内只有一个arguments变量,因此您无法arguments从封闭函数访问该变量是有道理的:
function f() {
function g() {
console.log(arguments); // will log ['blue'], not ['red']
}
g('blue');
}
f('red');
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1236 次 |
| 最近记录: |