在 JavaScript 中将事物存储在对象与数组中

AGx*_*162 4 javascript arrays

这更像是一个普遍的问题,而不是我需要解决的问题。我只是一个初学者,试图了解做事的正确方法。

我想知道的是我是否应该只使用对象作为原型(如果这是在这里使用的正确术语)或者是否可以使用它们来存储东西。

例如,在我正在进行的测试项目中,我想存储一些图像以备后用。我目前拥有的是这样的:

var Images = {
    james: "images/james.png",
    karen: "images/karen.png",
    mike: "images/mike.png"
};
Run Code Online (Sandbox Code Playgroud)

因为我知道位置,所以我想我也可以将它们放在一个数组中并适当地引用数组中的位置:

var images = ["images/james.png", "images/karen.png", "images/mike.png"];
images[0];
Run Code Online (Sandbox Code Playgroud)

使用这样的对象效果很好,但我想知道哪种方法更合适。是情境性的吗?是否有任何性能原因可以做一个而不是另一个?作为一个新程序员,我应该习惯一种更容易接受的方式吗?

提前感谢您的任何建议。

Bad*_*bra 8

介绍

与 PHP 不同,JavaScript 没有关联数组。这种语言中的两个主要数据结构是数组字面量( []) 和对象字面量( {})。使用一个或另一个实际上不是风格问题而是需要问题,因此您的问题是相关的。

来个客观的对比...

阵列 > 对象

  1. 数组字面量(间接地是一个对象)比对象字面量具有更多的方法。实际上,对象字面量是 的直接实例Object并且只能访问Object.prototype方法。数组字面量是一个实例Array并且可以访问,不仅可以访问Array.prototype方法,还可以访问方法Object.prototype(这是在 JavaScript 中设置原型链的方式)。

let arr = ['Foo', 'Bar', 'Baz'];
let obj = {foo: 'Foo', bar: 'Bar', baz: 'Baz'};

console.log(arr.constructor.name);
console.log(arr.__proto__.__proto__.constructor.name);

console.log(obj.constructor.name);
Run Code Online (Sandbox Code Playgroud)

  1. 在 ES6 中,对象字面量是不可迭代的(根据可迭代协议)。但是数组是可迭代的。这意味着您可以使用for...of循环来遍历数组字面量,但如果您尝试使用对象字面量(除非您定义[Symbol.iterator]属性),则它不会起作用。

let arr = ['Foo', 'Bar', 'Baz'];
let obj = {foo: 'Foo', bar: 'Bar', baz: 'Baz'};

// OK
for (const item of arr) {
  console.log(item);
}

// TypeError
for (const item of obj) {
  console.log(item);
}
Run Code Online (Sandbox Code Playgroud)

如果你想让一个对象字面量可迭代,你应该自己定义迭代器。您可以使用generator来做到这一点。

let obj = {foo: 'Foo', bar: 'Bar', baz: 'Baz'};

obj[Symbol.iterator] = function* () {
  yield obj.foo;
  yield obj.bar;
  yield obj.baz;
};

// OK
for (const item of obj) {
  console.log(item);
}
Run Code Online (Sandbox Code Playgroud)

数组 < 对象

  1. 如果出于某种原因,您需要描述性键,则对象字面量比数组更好。在数组中,键只是数字,这在您想要创建显式数据模型时并不理想。

// This is meaningful
let me = {
  firstname: 'Baptiste',
  lastname: 'Vannesson',
  nickname: 'Bada',
  username: 'Badacadabra'
};

console.log('First name:', me.firstname);
console.log('Last name:', me.lastname);

// This is ambiguous
/*
   let me = ['Baptiste', 'Vannesson', 'Bada', 'Badacadabra'];
   
   console.log('First name:', me[0]);
   console.log('Last name:', me[1]);
*/
Run Code Online (Sandbox Code Playgroud)

  1. 对象字面量是非常多价的,而数组则不是。对象字面量可以创建“惯用的”类、命名空间、模块等等......

let obj = {
  attribute: 'Foo',
  method() {
    return 'Bar';
  },
  [1 + 2]: 'Baz'
};

console.log(obj.attribute, obj.method(), obj[3]);
Run Code Online (Sandbox Code Playgroud)

数组 = 对象

  1. 数组文字和对象文字不是敌人。事实上,如果你一起使用它们,它们就是好朋友。该JSON格式,使集约利用这个强大的友谊:

let people = [
  {
    "firstname": "Foo",
    "lastname": "Bar",
    "nicknames": ["foobar", "barfoo"] 
  },
  {
    "firstName": "Baz",
    "lastname": "Quux",
    "nicknames": ["bazquux", "quuxbaz"]
  }
];

console.log(people[0].firstname);
console.log(people[0].lastname);
console.log(people[1].nicknames[0]);
Run Code Online (Sandbox Code Playgroud)

  1. 在 JavaScript 中,有一种被广泛使用的称为类数组对象的混合数据结构,即使您不一定意识到这一点。例如,arguments函数中的旧对象是一个类似数组的对象。DOM 方法也getElementsByClassName()返回类似数组的对象。正如你想象的那样,类数组对象基本上是一个特殊的对象字面量,其行为类似于数组字面量:

let arrayLikeObject = {
  0: 'Foo',
  1: 'Bar',
  2: 'Baz',
  length: 3 
};

// At this level we see no difference...
for (let i = 0; i < arrayLikeObject.length; i++) {
  console.log(arrayLikeObject[i]);
}
Run Code Online (Sandbox Code Playgroud)

结论

数组字面量和对象字面量各有优缺点,但根据此处提供的所有信息,我认为您现在可以做出正确的决定。

最后,我建议你尝试一下 ES6 引入的新数据结构:Map, Set, WeakMap, WeakSet。它们提供了许多很酷的功能,但在这里详细说明它们会让我们走得太远......