Is it possible to use the Object.create pattern to create a CustomEvent object?

114 views Asked by At

I know you can create a CustomEvent like this:

var wordCreated = new CustomEvent(
    "newWord", 
    {
        detail: {
            word: "hola",
            translation: "hi",
        },
        bubbles: true,
        cancelable: true
    }
);

I'm wondering how to do this without using new, with the Object.create pattern?

The problem I’m not seeing a solution to is that the CustomEvent takes two arguments: a string specifying a name for the event, and a configuration object containing bubbles, cancelable, and details properties. I’m not sure how to pass both the string and the object to Object.create.

Ultimately I expect to be able to use this custom event in the following standard way:

var p = document.querySelector('p'); // a random node
p.addEventListener('newWord', function(ev){ console.log(ev) });
p.dispatchEvent(wordCreated);
2

There are 2 answers

1
ivan.sim On BEST ANSWER

The answer to the question in your title "Is it possible to use the Object.create pattern to create a CustomEvent object?" is Yes. Now, the answer to the follow-up question "Shall you do it that way?" is probably No. As @MartinErnst pointed out, you're just going to end up re-inventing the wheel of what new is already doing.

The key difference between new and Object.create (in case you don't already know) is that Object.create creates an Object (notice the uppercase O) which inherits the prototype of the object specified as the first argument of Object.create. The new operator does the same thing with the additional step of invoking the constructor of the given object, before returning an instance of the specified object (notice the lowercase o).

So we can use Object.create to create an Object which inherits from the CustomEvent prototype with something like this:

var customEvent1 = Object.create(CustomEvent, {  
                     detail: {
                        writable:true, 
                        configurable:true, 
                        value: { word:"hola", translation:"hi" }
                      },
                      bubbles: {
                        writable:true,  
                        configurable:true, 
                        value:true 
                      },
                      cancelable:  {
                        writable:true,  
                        configurable:true, 
                        value:true 
                      },
                      type: {
                        writable:true,
                        configurable:true,
                        value:'newWord'
                      }
                    });

But doing a console.log(customEvent1) will yield an Object.

Contrast this to:

var customEvent2 = new CustomEvent("newWord", { 
                     detail: {
                      word: "hola",
                      translation: "hi",
                     },
                     bubbles: true,
                     cancelable: true
                   });

You will see that running console.log(customEvent2); will yield an instance of CustomEvent.

So when you try to invoke addEventListener() and dispatchEvent() on the above customEvent1 object, it will fail because that is an Object, not an Event. There are a few more things steps you will need to do to convert customEvent1 into a full Event object, which is essentially what new CustomEvent() is already doing.

Fiddle available here.

5
Verhaeren On

I think it should be something like:

obj.addEventListener("newWord", function(e) {alert(e.detail);});

var wordCreated = Object.create(CustomEvent.prototype, {
  "newWord": 
    {
        detail: {
            word: "hola",
            translation: "hi",
        },
        bubbles: true,
        cancelable: true
    }
});