JavaScript数组默认赋值语法混乱

时间:2018-07-10 10:12:34

标签: arrays javascript-objects

如果我像这样在JavaScript中创建函数构造函数:

function Emitter() {
  this.events={}
} 

然后我向其原型添加一个方法,如下所示:

Emitter.prototype.on = function(type,listener) {
  this.event[type] = this.events[type] | [];
  this.event[type].push(listener);
}

当我在Emitter的一个实例上两次调用方法时,为什么它不只是覆盖称为greet的原始属性并将其分配给第二个函数?我想我不了解发生的事情的局限性:

this.event[type] = this.events[type] | [];

var emtr = new Emitter();
emtr.on('greet',function(){
  console.log('Hello once'); 
});
emtr.on('greet', function(){
   console.log('Hello twice');
});

3 个答案:

答案 0 :(得分:2)

您应该为||使用OR而不是|,这是无效的:

this.event[type] = this.events[type] | [];

此外,您正在呼叫event而不是events。您应该具有:

this.events[type] = this.events[type] || [];

这样,如果this.events[type]不是undefined,它将保持原样。但是,如果为undefined,则会被分配为空数组:[]

下面的代码将成功地将两个函数添加到emtr.events['greet'](函数数组)中:

function Emitter() {
  this.events = {}
}

Emitter.prototype.on = function(type, listener) {
  this.events[type] = this.events[type] || [];
  this.events[type].push(listener);
}

var emtr = new Emitter();
emtr.on('greet', function() {
  console.log('Hello once');
});
emtr.on('greet', function(){
  console.log('Hello twice');
});

console.log(emtr.events['greet'])

所以您可以这样称呼他们:

emtr.events['greet'][0]();

还有

emtr.events['greet'][1]()

如果相反,您想替换侦听器,则不应该使用数组。指向一个函数而不是一个函数数组就足够了:

function Emitter() {
  this.events = {}
}

Emitter.prototype.on = function(type, listener) {
  this.events[type] = listener;
}

var emtr = new Emitter();
emtr.on('greet', function() {
  console.log('Hello once');
});
emtr.on('greet', function(){
  console.log('Hello twice');
});

emtr.events['greet'](); // notice how the first listener was replaced by the new one

通过这种方式,您可以使用emtr.events['greet']()来调用监听器。

答案 1 :(得分:1)

@Ivan完全正确的同时,他错过了您的主要问题“为什么?”

答案是,JS中的逻辑OR运算符用作赋值语句的一部分时,还充当空合并运算符。

基本上是这种情况

    let x = y || “default”;

右侧将求出第一个“真实”值并将其返回。在JS中,大多数事情都在逻辑运算中评估为true,除了false,0,null和其他与该问题无关的值。

因此,按照您的语法(由Ivan纠正),您要告诉JS将第一个正确的东西分配给events [type]属性。本身(如果不为null,未分配,0等,则为true),否则为空数组。

第一次添加事件时,该事件不会被分配,因此会添加一个空数组。随后,将数组eval设置为true,因此您只需继续将属性重新分配给它本身就没有效果。

有道理吗?

答案 2 :(得分:0)

function Emitter() {
    this.events = []
}

Emitter.prototype.on = function (type, listener) {
    
    this.events[type] = this.events[type]||[]

    this.events[type].push(listener);
}

Emitter.prototype.emit = function(type){
    var listener = this.events[type].pop()
    if(this.events[type].length>=0)
        listener()
    else
        console.log('Nothing to emit')
}


var emtr = new Emitter();
emtr.on('greet',function(){
  console.log('Hello once'); 
});

emtr.emit('greet')