Javascript数组的行为方式不同

时间:2017-11-22 17:38:59

标签: javascript arrays object

您好我附上我的Firefox控制台的屏幕截图,并想知道为什么数组在javascript中的行为如此。

enter image description here

我试图理解js中的... in和for ...但遇到了这个问题。我现在明白,因为...正在打印只是键,而...正在打印值部分。但我不明白为什么阵列首先采用键值对?

我认为,当Array也是一个对象时,它可以采用A键:值对作为输入但是当我在console.log(a)时为什么它不打印foo:bar,即使打印[" FOO"打印" bar"。是否有一些我错过并且无法理解的概念?

但Chrome浏览器显示如下:

enter image description here

在这种情况下,打印数组a给我[1,2,3,foo:" bar"]作为输出但是如果我定义

var b=[1,2,3,foo: "bar"] 
它给了我意想不到的代币。为什么会这样?

2 个答案:

答案 0 :(得分:5)

因为Javascript中的数组可以包含成员(即数组中的内容),但也是对象,因此可以具有键/值属性。

这可能有点令人困惑,所以让我们使用装运箱的比喻:

enter image description here

盒子里面装有东西(会员),但它也有盒子本身的信息(送货地址,寄信地址等......即属性)。但是,他们在外部上还有一个“发货清单”,其中详细说明了内部框中的内容,这使得框的内容也是它的属性

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属性的对象,一组标记为0length - 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 
  + "]");
}

进一步阅读:https://stackoverflow.com/a/5048482/1636522