This will keep listeners alive until add-on is unloaded, which is exactly a problem! In a lot of cases that's unnecessary overhead, in a lot of cases both your listener and object can be GC-ed a lot faster than add-on is unloaded. For example see this comment:
https://github.com/mozilla/addon-sdk/pull/944/files#r3817523

What's even more important in a lot of cases such API introduced circular references that will cause both wrapper and listener to stay alive with a rest of the object graph they refer to.

Here is a very common case:
```js
let Foo = Class({
  initialize: funciton(element) {
     this.doSomething = this.doSomething.bind(this);
     on("some-event", this.doSomething);
  },
  destroy: function() {
     off("some-event", this.doSomething);
  }
})
```

In this very common pattern, you introduced circular ref between `Foo`
instance and bound `this.doSomething` which means only chance for
GC to claim these is either add-on unload or manually call of `destroy`.

On top of this observers will still be fired once after add-on is unloaded,
and you'll have to clear up listeners manually.

On the other hand consider this alternative:

```js
function Foo(element) {
   function handler() {
      doSomethingWith(element)
   }
   on("some-event", handler);
   refs(this).add(handler);
}
```

In this case, which I'd argue is a lot simpler, you just associate handler to the foo instance and that's it. As soon as Foo instance is no longer referenced (which can be a lot earlier that add-on unload) will be GC-ed with all the event handlers associated with it. In addition you no longer have to manually destroy or remove listeners. This also means GC can schedule it's mark and sweep operations without stressing JS runtime too much.