1

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);
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
  • I'm deleting my answer for now, until I get a chance to look more into it. Apologies. – ivan.sim Nov 18 '14 at 19:30
  • Why not doing `p.dispatchEvent(wordCreated);` using the event created in your first snippet? Thats what `CustomEvent` is for. Reinvent the wheel? – Martin Ernst Nov 18 '14 at 19:40
  • I'm trying to see how to apply the `Object.create` pattern in this context. Yes, the existing pattern works fine. –  Nov 18 '14 at 20:08

2 Answers2

2

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.

Community
  • 1
  • 1
ivan.sim
  • 8,972
  • 8
  • 47
  • 63
  • `CustomEvent.prototype` is non-configurable and non-writable so you can't redefine it that way. It results in `myCustomObject` having all configurable properties (*type* included) undefined. – Martin Ernst Nov 18 '14 at 19:26
0

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
    }
});
Verhaeren
  • 1,661
  • 9
  • 10
  • Yes, indeed. Replacing the coma with a colon remove the syntax error. Still I don't know if this could work. I'm investigating. I like this question. – Verhaeren Nov 18 '14 at 18:10
  • The isim's answer is the right way to do it. My upvote for him. I will mark this question as favorite, because I'm going to use this approach soon. – Verhaeren Nov 18 '14 at 18:26
  • I don't get what was wrong with isim's code. It was working fine on the fiddle. – Verhaeren Nov 18 '14 at 19:49
  • @Verhaeren I have updated my answer with why calling `dispatchEvent()` on `CustomEvent` objects created with `Object.create()` will fail. – ivan.sim Nov 23 '14 at 06:48
  • The second argument to `Object.create` needs to be a property descriptors object. –  Nov 23 '14 at 06:50