这是一个普遍的问题,而不是我需要解决的问题。我只是一个初学者,试图了解正确的做事方式。
我想知道的是,我是否应该只使用对象作为原型(如果这是在这里使用的正确术语),或者是否可以使用它们来存储东西。
例如,在我正在研究的测试项目中,我想存储一些图像以供日后使用。我现在拥有的是:
var Images = {
james: "images/james.png",
karen: "images/karen.png",
mike: "images/mike.png"
};
因为我知道位置,我想我也可以将它们放在一个数组中并适当地引用数组中的位置:
var images = ["images/james.png", "images/karen.png", "images/mike.png"];
images[0];
使用像这样的对象可以很好地工作,但我想知道哪种方法更合适。这是情境化的吗?是否有任何性能原因可以做到另一个?有一种更为公认的方式,作为一名新程序员,我应该习惯吗?
提前感谢任何建议。
答案 0 :(得分:3)
实际上,你声明事物的方式会带来“关联数组和数组之间的差异”。
JS中的关联数组与对象非常相似(因为它是一个):
当您撰写var a = {x:0, y:1, z:3}
时,您可以使用x
(对象)或a.x
(关联数组)访问a["x"]
。
另一方面,常规数组可以被视为关联数组,它使用无符号整数作为索引的ID。
因此,要回答您的问题,我们应该选择哪一个?
这取决于:每当我需要在名称/标签上添加对象时,我会使用对象(例如,通常不用于变量集合)。如果你要存储的东西的类型是同质的,你可能会使用一个数组(但如果你真的想要,你仍然可以找到一个对象),如果你的一些/所有东西的类型都不同于你应该去的类型一个对象(但理论上你仍然可以去一个数组)。
我们来看看:
var a = {
x:0,
y:0,
z:0
}
x
,y
,z
都有不同的含义(一个点的组成部分),因此一个对象在实现一个点时更好(就语义而言)。
因为var a = [0,0,0]
没有比一个对象更有意义,所以我们不会在这种情况下使用数组。
var storage = {
one:"someurl",
two:"someurl2",
three:"someurl3",
}
是正确的,但我们不需要每个项目的明确名称,因此我们可能会选择var storage = ["someurl","someurl2","someurl3"]
最后但并非最不重要的是,“困难”的选择:
var images = {
cathy: "img/cathy",
bob: "img/bob",
randompelo: "img/randompelo"
}
和
var images = ["img/cathy","img/bob","img/randompelo"]
是正确的,但选择很难。因此,要问的问题是:“我们需要一个有意义的ID吗?”。
假设我们使用数据库,一个有意义的id会更好地避免每次你想做某事时的几十个循环,另一方面如果它只是一个没有任何重要性的列表(索引不重要,ex:create)每个元素元素的图像)也许我们可以尝试去一个数组。
当您在数组和对象之间犹豫时要问的问题是:键/ ID在含义方面是否重要? 如果他们是一个对象,如果他们不去寻找阵列。
答案 1 :(得分:2)
你纠正它是情境性的,但一般来说,通过仅允许一组有限的支持选项限制你的程序并不是一个好主意:
var Images = {
james: "images/james.png",
karen: "images/karen.png",
mike: "images/mike.png"
};
当然,除非您碰巧知道这些将是唯一可能发生的情况 - 并且您主动不想支持其他情况。
假设您不想限制可能性,那么您的数组方法就可以了 - 尽管我个人可能会使用带有标识符的对象数组,因此您不必在其他位置跟踪索引。
类似的东西:
var userProfiles = [
{"username": "james", "image": "images/james.png"},
{"username": "karen", "image": "images/karen.png"},
{"username": "mike", "image": "images/mike.png"}
];
答案 2 :(得分:1)
与PHP不同,JavaScript没有关联数组。此语言中的两个主要数据结构是数组文字([]
)和对象文字({}
)。使用一个或另一个并不是风格问题,而是需要的问题,所以你的问题是相关的。
让我们进行客观的比较......
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);

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);
}

如果要使对象文字可迭代,则应自行定义迭代器。您可以使用生成器来执行此操作。
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);
}

// 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]);
*/

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

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]);

arguments
对象是类似于数组的对象。像getElementsByClassName()
这样的DOM方法也会返回类似数组的对象。如您所想,类似数组的对象基本上是一个特殊的对象文字,其行为类似于数组文字:
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]);
}
&#13;
数组文字和对象文字有各自的优点和缺点,但是根据这里提供的所有信息,我认为你现在可以做出正确的决定。
最后,我建议您尝试ES6引入的新数据结构:Map
,Set
,WeakMap
,WeakSet
。它们提供了许多很酷的功能,但在这里详细介绍它们会让我们走得太远......