Javascript 在JS数组中使用命名键

Javascript 在JS数组中使用命名键,javascript,arrays,Javascript,Arrays,我正在研究Zakas在数组中使用命名键(与在对象中使用命名键相反),对此我感到困惑。见评论: function EventTarget() {} EventTarget.prototype = { constructor: EventTarget, addListener: function(type, listener) { if (!this.hasOwnProperty("_listeners")) { // Why isn'

我正在研究Zakas在数组中使用命名键(与在对象中使用命名键相反),对此我感到困惑。见评论:

function EventTarget() {}

EventTarget.prototype = {

    constructor: EventTarget,

    addListener: function(type, listener) {

        if (!this.hasOwnProperty("_listeners")) {
            // Why isn't this: `this._listeners = {};`
            this._listeners = [];
        }

        if (typeof this._listeners[type] === "undefined") {
            this._listeners[type] = [];
        }

        this._listeners[type].push(listener);
    },

    // more stuff
}

var target = new EventTarget();
target.addListener("message", function(event) {
    console.log("Message is " + event.data);
});
他的代码工作得很好(就像用数组替换对象文字一样),但我的理解是,如果要按名称访问内容,应该使用对象。从:

许多编程语言支持带有命名索引的数组。
具有命名索引的数组称为关联数组(或哈希)。
JavaScript不支持带有命名索引的数组。
在JavaScript中,数组总是使用编号索引


Zakas使用这样的数组有什么好的理由吗?你能解释一下吗?或者,这是我应该服从的吗?

我能看到的唯一原因是:迷惑人。JavaScript并没有强制执行任何东西,实际上,因为所有东西都是一个对象,所以您几乎可以做任何您想做的事情。这家伙使用数组来存储命名属性,但他很可能使用了函数或其他任何东西

编辑:几乎所有的东西都是一个对象(我可能会想到,有人可能会尝试在
未定义的
上设置一个属性,因为JavaScript中最常见的错误之一是
类型错误:未定义的不是一个对象
。JavaScript叹息道,你为什么这样对我们

Zakas使用这样的数组有什么好的理由吗

从引用的代码中,我想不出一个,不。他没有使用
\u listeners
指数组这一事实。坦率地说,它看起来就像一个拼写错误。因为它可以工作(因为JavaScript的普通数组是对象),所以没有捕捉到拼写错误。嗯,直到你捕捉到它为止。:-)

除非您没有引用一些代码,然后将array enries*添加到该数组中,否则没有理由在那里使用数组(可以说有几个理由不这样做)


*“array entry”=其键为数组索引的属性。那么什么是“数组索引”?“字符串属性名P是数组索引,当且仅当
ToString(ToUint32(P))
等于P且
ToUint32(P)
不等于
232−1
“()

数组只是特殊对象

a=[]
a[7]=9
a["abc"]=20
a["xxx"]=30
for (i in a) console.log("value",i,a[i])
产出

value 7 9
value abc 20
value xxx 30

我倾向于说这是一个打字错误,但很可能是有意的,那么下面是我能想到的唯一的功能用例。。。(警告:可能会产生分歧)

假设观察者/事件模式是一个可以应用于任何对象的通用概念,“private”(用下划线表示)
\u侦听器
属性可能永远不需要被目标知道,那么它包含的数据对对象本身来说是多余的,这是有争议的

也就是说,如果目标对象被序列化,则可能不希望传输此类数据。以下示例说明了JSON序列化程序如何忽略
foo.baz
中的非数字数组属性-类似地,在您自己的示例中,所有附加的事件数据都将被删除:

var foo = {
    bar: {},
    baz: []
};

foo.bar['p1'] = foo.baz['p1'] = 1;
foo.bar['p2'] = foo.baz['p2'] = 2;

console.log( JSON.stringify(foo) ); // {"bar":{"p1":1,"p2":2},"baz":[]}

“一切都是对象”。不是所有的!未定义的不是对象
typeof undefined==“undefined”
如果
type
为整数,则此代码正确。此代码仍然有效,因为它在数组对象上设置属性,而不是在实际数组中设置属性。检查
Object.getOwnPropertyNames(this.\u侦听器)
,然后检查
Object.keys(this.\u侦听器)
this.\u侦听器
应该是一个对象,而不是一个数组。@hindsmost:代码是正确的(因为它是函数型的),即使
类型
不是整数(而且看起来很可能不是,更可能是像
“click”
)这样的字符串。@t.J.Crowder,除非有人传递字符串
“length”
用于
类型
。然后令人兴奋的事情发生了。@RaymondChen:的确,这就是为什么ES6有
Map
。伊玛给了你一票,因为该死的伙计,这是一种横向思维。我不认为这是滥用JS结构的一个好理由,但它发人深省。