JavaScript event model Code _javascript Tips

Source: Internet
Author: User
Tags abs closure
This section discusses the topic of event handling in some depth, and if you don't quite understand the concepts of patterns, closures, and object-oriented, just wait and see when you've finished reading about it, and believe you'll have a lot to gain.

1 Event Handling mode

In the field of programming, "event handling" is a pattern that, when an object is affected by external influences, changes the state by notifying the object, or an associated object, of the change in the way the message is made, which is the basic principle of event handling. The object responsible for notification state changes is called "message", and the property that executes the response action is called the event agent.
For example, here is an application of a simple event-handling pattern:

function Dispatchevent (owner, EventType, EventArgs)
{
if (owner && owner["on" +eventtype])
settimeout (function () {owner["on" +eventtype] (EventArgs)}, 1);
}

function Randomserials (len)
{
function randomsignal ()
{
return Math.random () > 0.5? 1:0;
}
var ret = [];
for (var i = 0; i < len; i++)
{
Ret.push (Randomsignal ());
}
return ret;
}

function Differ (OBL)
{
var buffer = new Array (OBL);
var time = 0;

This.readbuffer = function ()
{
var buf = buffer;

Buffer = new Array (OBL);
Time = 0;

return buf;
}

This.buffersize = function ()
{
return OBL;
}

This.input = function (serials)
{
for (var i = 1; i < serials.length; i++)
{
var signal = Math.Abs (Serials[i]-serials[i-1]);
buffer[time++% obl] = signal;
if (signal)
Dispatchevent (This, "Signalchange",
{input:serials, time:time, Buffer:buffer.slice (0)});
}
}
}

var inputserials = randomserials (20);
alert (inputserials);
var diff10 = new Differ (20);
Diff10.input (inputserials);
Alert (Diff10.readbuffer ());

Diff10.onsignalchange = function (EventArgs)
{
alert (eventargs.time);
}

Diff10.input (inputserials);

In the example above, the function dispatchevent is responsible for assigning events, Onsignalchange is the event agent, and in this differential system DIFF10, when the level of the input signal changes (from 0 to 1 or 1 to 0), Triggers the appropriate event Onsignalchange and passes the current input signal, timing, and current output cache as event arguments to the event handler.

Diff10.onsignalchange = function (EventArgs)
{
alert (eventargs.time);
}

Is the programmer-specified event handler, where we print the input signal timing when the input level changes.

2 Definition of User event interface

In the previous example, we just defined a function dispatchevent to assign an event, but it can also be seen as a complete user event interface, and now we review the function to figure out what it does:

function Dispatchevent (owner, EventName, EventArgs)
{
if (owner && owner["on" +eventname])
settimeout (function () {owner["on" +eventname] (EventArgs)}, 1);
}

This function receives three arguments, and its first argument is an object that specifies the "owner" of the event, that is, who receives and handles the event. In the above example, this owner is the differ object itself, which is
Dispatchevent (This, "Signalchange", {input:serials, time:time, buffer:buffer});
The owner parameter passed in is this, in fact the event pattern allows other types to be the owner of the event assignment, especially in certain patterns where the initiator of the event and the recipient of the event can be not the same object. This can be seen in the observer pattern introduced in section 4.
The second parameter is a string representing the type of event that determines the name of the event agent, and the name of the event agent, based on the specification of the event model, is "on" + event type, for example, in the example above, the event type is signalchange and the corresponding event agent is Onsignalchange.
The third parameter is an event parameter object that determines the parameter passed to the event receiver, in the example above, which passes the input, time, and buffer three properties, representing the current input sequence, timing, and output cache values of the event.
The content of the Dispatchevent function itself is simple, it simply ensures that the event proxy for the caller is invoked and that the event arguments are passed in correctly to the event agent. As for how the event agent handles event arguments, it doesn't care.

3 Event Agents and event registrations

In event handling mode, the process of specifying an event handler for an event proxy is called Event registration. In the above example, Diff10.onsignalchange is an extremely simple event broker, and its event registration process is also extremely simple-it is done directly by assigning values.
In fact, depending on the design, the event agent can have more complex registration methods, such as Dom-level-2 AddEventListener and RemoveEventListener, we can implement similar event registration method, To support registering multiple event event handling methods for an event agent. To implement it, we refine the event interface and modify the example above as follows:

function EventManager (owner)
{
Owner = Owner | | This

This.dispatchevent = function (EventType, EventArgs)
{
var events = owner["on" +eventtype];
if (Events && typeof (events) = "function")
events = [events];
if (owner && events)
{
for (var i = 0; i < events.length; i++)
{
SetTimeout (
(function (i) {return function () {events[i] (EventArgs)}
}) (i), 1
);
}
}
}

This.addeventlistener = function (EventType, closure)
{
if (owner["on" +eventtype] = = null)
{
owner["on" +eventtype] = [];
}
var events = owner["on" +eventtype];
if (Events && typeof (events) = "function")
events = [events];
Events.push (closure);
}

This.removeeventlistener = function (EventType, closure)
{
var events = owner["on" +eventtype];
if (Events && typeof (events) = "function")
events = [events];

for (var i = 0; i < events.length; i++)
{
if (events[i] = = closure)
Events.splice (i, 1);
}
}
}

function Randomserials (len)
{
function randomsignal ()
{
return Math.random () > 0.5? 1:0;
}
var ret = [];
for (var i = 0; i < len; i++)
{
Ret.push (Randomsignal ());
}
return ret;
}

function Differ (OBL)
{
var buffer = new Array (OBL);
var time = 0;

Eventmanager.call (this); Apply Enventmanager Component.

This.readbuffer = function ()
{
var buf = buffer;

Buffer = new Array (OBL);
Time = 0;

return buf;
}

This.buffersize = function ()
{
return OBL;
}

This.input = function (serials)
{
for (var i = 1; i < serials.length; i++)
{
var signal = Math.Abs (Serials[i]-serials[i-1]);
buffer[time++% obl] = signal;
if (signal)
This.dispatchevent ("Signalchange",
{input:serials, time:time, Buffer:buffer.slice (0)});
}
}
}

var inputserials = randomserials (20);
alert (inputserials);
var diff10 = new Differ (20);
Diff10.input (inputserials);
Alert (Diff10.readbuffer ());

var eventHandler1 = function (EventArgs) {
alert (eventargs.time);
}

var eventHandler2 = function (EventArgs) {
alert (Eventargs.buffer);
}

Diff10.addeventlistener ("Signalchange", eventHandler1);
Diff10.addeventlistener ("Signalchange", eventHandler2);
Diff10.input (inputserials);

Diff10.removeeventlistener ("Signalchange", eventHandler1);

In the above example, we have created a EventManager type, which defines three object methods, and the Dispatchevent method is similar to the one in the previous example, which is used to assign events. The other AddEventListener and RemoveEventListener are used to register and unregister the event handler functions.
In the differ type, we pass the Eventmanager.call (this), and apply an instance of the EventManager type to the differ prototype (the underlying mechanism for this issue is left for further discussion later). Then call This.dispatchevent to assign the event.
When registering an event for the differ instance's Onsignalchange event agent, you will find that it is very similar to the standard DOM event model:
Diff10.addeventlistener ("Signalchange", eventHandler1);
Diff10.addeventlistener ("Signalchange", eventHandler2);
Diff10.removeeventlistener ("Signalchange", eventHandler1);

When you run this example, you'll find an interesting place, that is diff10.input (inputserials); The triggering event did not execute EventHandler1 and eventHandler2, but only eventHandler2. The reason is:
Diff10.removeeventlistener ("Signalchange", eventHandler1);
The trigger before the event is executed, because the event mechanism is an "asynchronous callback" mechanism, and questions about synchronization and Asynchrony are discussed later.

4 Standard Mode: Event dispatch and reception

In event handling mode, the dispatcher of the event is responsible for sending the message, and the recipient of the event is responsible for processing the message. In the previous example, they were done by the same object (Differ).
However, in fact, in event handling mode, the sending and receiving of messages is not required to be completed by the same object, in some modes they are different objects, the most common one being "observer" mode, and the following is the example of the difference system being rewritten as observer mode:

function Dispatchevent (owner, EventType, EventArgs)
{
if (owner && owner["on" +eventtype])
settimeout (function () {owner["on" +eventtype] (EventArgs)}, 1);
}

function Randomserials (len)
{
function randomsignal ()
{
return Math.random () > 0.5? 1:0;
}
var ret = [];
for (var i = 0; i < len; i++)
{
Ret.push (Randomsignal ());
}
return ret;
}

function Differobserver (differ)
{
This.differ = differ;
Differ.setobserver (this);
}

function Differ (OBL)
{
var buffer = new Array (OBL);
var time = 0;
var observer = NULL;

This.input = function (serials)
{
for (var i = 1; i < serials.length; i++)
{
var signal = Math.Abs (Serials[i]-serials[i-1]);
buffer[time++% obl] = signal;
if (signal)
DISPATCHEVENT (Observer, "Signalchange", {sender:this, input:serials, Time:time, Buffer:buffer.slice (0)});
}
}

This.setobserver = function (OBS)
{
Observer = OBS;
Observer.readbuffer = function ()
{
var buf = buffer;

Buffer = new Array (OBL);
Time = 0;

return buf;
}
Observer.buffersize = function ()
{
return OBL;
}
}
}


var inputserials = randomserials (20);
alert (inputserials);
var diff10 = new Differ (20);
Diff10.input (inputserials);
var diffobs = new Differobserver (DIFF10);
Alert (Diffobs.readbuffer ());

Diffobs.onsignalchange = function (EventArgs)
{
if (diff10 = = Eventargs.sender)
alert (eventargs.time);
}

Diff10.input (inputserials);

The event dispatcher in the example above is the differ type, and the event receiver is the Differobserver type, so the agent for the event registration is the Differobserver attribute, and in the event arguments we send, we add a property sender, It references the actual sending object of the event

Original: Http://bbs.51js.com/thread-69808-1-1.html by Moon Shadow

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.