您好我附上我的Firefox控制台的屏幕截图,并想知道为什么数组在javascript中的行为如此。
我试图理解js中的... in和for ...但遇到了这个问题。我现在明白,因为...正在打印只是键,而...正在打印值部分。但我不明白为什么阵列首先采用键值对?
我认为,当Array也是一个对象时,它可以采用A键:值对作为输入但是当我在console.log(a)时为什么它不打印foo:bar,即使打印[" FOO"打印" bar"。是否有一些我错过并且无法理解的概念?
但Chrome浏览器显示如下:
在这种情况下,打印数组a给我[1,2,3,foo:" bar"]作为输出但是如果我定义
var b=[1,2,3,foo: "bar"]
它给了我意想不到的代币。为什么会这样?
答案 0 :(得分:5)
因为Javascript中的数组可以包含成员(即数组中的内容),但也是对象,因此可以具有键/值属性。
这可能有点令人困惑,所以让我们使用装运箱的比喻:
盒子里面装有东西(会员),但它也有盒子本身的信息(送货地址,寄信地址等......即属性)。但是,他们在外部上还有一个“发货清单”,其中详细说明了内部框中的内容,这使得框的内容也是它的属性
var box = [thing1ToShip, thing2ToShip]; // box contents
box.shippingAddress = 'some address'; // a box property (aka box['shippingAddress'])
box.returnAddress = 'some address'; // a box property (aka box['returnAddress'])
// The "manifest"
box[0] === thing1ToShip; // both content AND a box property
box[1] === thing2ToShip; // both content AND a box property
box.length === 2; // also a box property
For
/ of
循环迭代所提供对象的 iterable属性,因此只返回数组本身的值。这是因为Javascript中的对象可以定义它们应该如何迭代,而Arrays定义自己根据length
进行迭代,而不是键。
For
/ in
循环遍历所提供对象的可枚举属性。因为数组的成员也是属性(a[0]
),所以你得到 你指定的键/值对和数组成员。
至于:
var b = [1,2,3,foo:“bar”]
它给了我意想不到的代币。为什么会这样?
那只是因为你写的是无效的Javascript。在创建数组时,无法定义数组的名称/值属性,只能定义其成员。要创建数组(使用正确的[thing1, thing2, thing3]
语法),必须添加属性。
如果要简单地向新阵列添加属性,可以使用Object.assign
:
var b = Object.assign([1,2,3], {foo: "bar"});
换句话说,首先创建一个数组[1,2,3]
,然后将第二个参数({foo: "bar"}
)的属性赋给它......并且因为该对象中只有一个属性相当于“向数组中添加foo: 'bar'
”属性。
答案 1 :(得分:1)
这是一个很好的问题:-)粗略地说,数组是一个具有length
属性的对象,一组标记为0
到length - 1
的属性,以及一对具体功能。我们几乎可以说a = [1, 2, 3]
是以下的捷径:
a = { 0: 1, 1: 2, 2: 3, length: 3 }
实际上,您可以使用普通对象轻松模拟数组。
对象是键值对的集合,如字典。密钥可以是任意字符串,值可以是任何类型的数据。在JavaScript中,几乎所有东西都是一个对象。数组是一个对象,一个函数是一个对象,甚至像数字和字符串这样的原子数据也可以像对象一样被操纵,实际上,JavaScript秘密地创建了一个对象以包装原子数据。
有两种方法可以创建对象。通常,您会看到基于括号({}
和[]
)或new
关键字的文字符号。字面符号只是语法糖,实际上,您的计算机在两种情况下都执行完全相同的指令序列。换句话说,o = {}
与o = new Object()
相同,a = []
与a = new Array()
相同。
是的,当您编写a = []
时,您隐含地创建了Array
类的实例,这就是使数组成为特殊对象的原因:-)如上所述,数组是一个对象具有其他功能,这些功能继承自Array
类。 indexOf
方法就是其中之一(在控制台中键入Array.prototype
以列出所有内容):
var a = ["a", "b", "c"];
a.indexOf("b"); // 1
直到最近,只要您没有从对象本身调用Array
特定方法,您就可以通过向普通对象添加length
属性来轻松欺骗JavaScript并将其用作阵列。 JQuery利用了这种技术:http://api.jquery.com/Types/#ArrayLikeObject。
var o = { length: 0 };
Array.prototype.push.call(o, "a", "b");
console.log(o, Array.prototype.slice.call(o));
今天这有点难以实现,例如,你必须实现一个迭代器才能在for ... of
循环中使用普通对象:
var o = {
0: "a",
1: "b",
2: "c",
length: 3
};
// o[Symbol.iterator] = Array.prototype[Symbol.iterator];
// works as well, but I want you to see there is no magic :-)
o[Symbol.iterator] = function() {
return {
i: 0,
o: this,
next: function() {
var o = this.o;
var i = this.i++;
return {
value: o[i],
done: i === o.length
}
}
};
};
for (var x of o) {
console.log(x);
}
for (var x in o) {
console.log(x, o[x]);
}
请注意,JavaScript会忽略length
循环中true数组的for ... in
属性。在我的拙见中,这是一个值得怀疑的选择,最有可能导致坦率的新手脑中出现蓝屏......
var a = [1, 2, 3];
a["i'm"] = "your father";
console.log("length", a.length);
for (var k in a) {
console.log(k, a[k]);
}
最后一句话,不要对Chrome控制台的输出感到困惑,它显示阵列的方式是谷歌开发人员的随意选择。看,打印东西与编写源代码无关,的确,你有力量!
printArray([1, 2, 3]);
function printArray(a) {
console.log("["
+ a.join(", ") + ", "
+ "length: " + a.length
+ "]");
}