我正在阅读David Flanagan的JavaScript:The Definitive Guide,它可能是世界上最胖的JavaScript书籍。在简要描述数组初始化器时,Flanagan说"每次数组初始化器时都会计算数组初始值设定项中的元素表达式 被评估"。这意味着什么。我的练习结果让我更加困惑:
var a = 50;
var b = 70;
var array = [a+b, 50];
console.log (array [0]); //120
a = 60;
console.log (array [0]); //120
var other = array;
console.log (other [0]); //120
我认为在将值改为60之后结果将是130,因为表达式将被重新评估。但事实并非如此。我知道我完全弄错了。有人可以解释一下弗拉纳根试图在那句话中解释什么吗?
答案 0 :(得分:2)
他的意思是,当数组文字表达式(" re&#34 ;-)被评估时,它的内容也是如此。
function makeArray() {
return [a];
}
var a = 0;
console.log(makeArray()); // [0]
a = 1;
console.log(makeArray()); // [1]
所以,实际上没什么特别的,只是默认的表达行为。
答案 1 :(得分:1)
在这里,您将array
分配给数组变量,它将存储该值,直到该变量(除非您修改该变量)超出范围。在第二个语句中,您将重用#34; array"所指向的相同数组。变量。第三个陈述只是将参考分配给"数组"变量到另一个变量并访问相同的元素。
仅第一次评估a + b语句,并将结果数组保存为值引用。最后一个语句是传递值的示例(Javascript总是按值传递),其中"数组"的副本变量创建为"其他"和"其他"也指向" array"指向的相同内存引用变量
答案 2 :(得分:1)
你错误引用了作者;他实际上说的是
每次计算数组初始值设定项时,都会计算数组初始化程序中的元素表达式。
而不是术语"数组初始化程序"如果他说"数组文字"它将更清晰,更符合常见用法。如果我们采用"阵列初始化器的常识解释"作为数组值变量"的含义"初始化器,那么这样的初始化器可以是数组文字,但也可以是任何数组表达式。 (话虽如此,似乎规范使用了术语"数组初始值设定项"用于"数组文字"在Section 12.2.5中,因此作者的用法不是这种技术意义上的错误。)另一方面,数组文字(基本上,形式为[...]
)的任何东西都可以用作初始化程序,但也可以在其他地方使用。
他似乎试图说的是一个数组文字,例如
[a]
每次重新评估自身时,重新评估a
,例如重新执行某个函数时。如果你考虑一下,这很明显。很难看出它如何以其他方式发挥作用。所以功能
function foo(x) { return [x]; }
将在调用[1]
时返回数组foo(1)
,并在调用[2]
时返回数组foo(2)
,因为数组文字[x]
是每次调用函数时都会评估。
这与绊倒你的问题完全不同,即
var a = 22;
var b = [a];
a = 42;
console.log(b);
不更改b
以获得值[42]
。此行为与如何(重新)评估数组初始值设定项或(重新)评估其组件元素无关。与JavaScript变量和引用的工作方式有关。如果 b
将b
的动态引用存储为其元素,则上述内容会更改a
的值,但JavaScript没有动态可更新的概念引用。换句话说,console.log(b)
行确实正在评估b
,但这只会返回b
已经存在的内容。它不会(重新)评估最初用于设置[a]
的表达式b
。在设置b
的值的语句之后,[a]
碰巧对评估b
产生的价值所带来的这一事实立即丢失,此时b
现已拥有价值[22]
。
还要考虑以下示例,它完全类似于:
var a = 1, b = 2, c = a + b;
a = 42;
console.log(c);
此处,当c
的值稍后更改时,没有人会期望作为a
的初始值给出的表达式会发生变化。 c
是3,它将一直显式重新分配。在console(c)
行,是的,我们正在"评估" c
,但这只是检索c
的值,而不是重新评估过去曾经用于为c
赋值的某些表达式。还有一些其他声明式语言范例,其中事物可能以这种方式表现,但不是JavaScript。