2

In Lua I've made my own Event system and I wanted to convert and use it in JavaScript, here's the code in Lua:

TriggerEvent = function(Name, ...)
    local EventID = nil;

    for Event2ID, Table in pairs(Event) do
        if(Table.Active and Table.Name == Name) then
            EventID = Event2ID;
            break;
        end
    end

    if(EventID == nil) then
        return false;
    end

    for ListenerID, Table in pairs(Event[EventID].Listener) do
        if(Table.Active) then
            Table.Function(...);
        end
    end
    return true;
end

Which works flawlessly. Here's what I have for JavaScript:

TriggerEvent = function(Name, ...) {
    var
        EventID = undefined
    ;

    for(Event2ID = 0, Length = Event.length; Event2ID < Length; Event2ID++) {
        if(Event[Event2ID].Active && Event[Event2ID].Name == Name) {
            EventID = Event2ID;
            break;
        }
    }

    if(EventID == undefined) {
        return false;
    }

    for(ListenerID = 0, Length = Event[EventID].Listener.length; ListenerID < Length; ListenerID++) {
        if(Event[EventID].Listener[ListenerID].Active) {
            Event[EventID].Listener[ListenerID].Function(...);
        }
    }
    return true;
}

Which doesn't work at all.

Example usage:

WebsiteConnected = function(Website, Test) {
    Website.SetTitle("Hello World");

    console.log(Website.GetTitle() + " connected! " + Test);
    return true;
}

CreateEvent("WebsiteConnected"); // Moved down.
AddEventListener("WebsiteConnected", WebsiteConnected);
TriggerEvent("WebsiteConnected", (Website || {}), "Test"); // Moved down.
  • Have you heard about JS [arguments object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions#Using_the_arguments_object)? – hindmost Aug 19 '14 at 14:13
  • I just tried it based on what I read from that article, but it did not work too well for me. Mind giving an example showing how to do what I'm trying to do? – SkittlesAreFalling Aug 19 '14 at 14:18

2 Answers2

3

Here's how "optional" arguments work in Javascript:

If you write a function like so:

function doSomething(arg1, arg2, arg3) {
    // Insert quality code here :-)
}

It is valid Javascript to call this function (or any other function for that matter) with any number of arguments.

If you pass in less than the three arguments specified, the remaining arguments will default to null.

If you pass in more than three arguments, the extra arguments will be ignored.

If you want to "overload" a function, there is no such thing in Javascript. If a function needs to accept two different types for one parameter, the function must check the type of what is passed in and behave accordingly.

Also, there is the arguments object, which provides an array-like interface to the arguments passed to the currently executing function. For some reason, there was a quirk in the development of the language that the arguments object behaves much like an array, but isn't an array. :-/

Vivian River
  • 31,198
  • 62
  • 198
  • 313
  • In other words, what I'm trying to do isn't possible? – SkittlesAreFalling Aug 19 '14 at 14:23
  • 9
    _the remaining arguments will default to null_. AFAIK they will default to `undefined` – hindmost Aug 19 '14 at 14:27
  • Okay thank you, I'll just pass an object with the variables I want inside. – SkittlesAreFalling Aug 19 '14 at 14:29
  • For what it's worth, that's how a lot of functions in the popular jQuery library work. They take one argument that contains a number of fields. – Vivian River Aug 19 '14 at 14:40
  • In this example, is there a way to pass in `arg1` and `arg3` but not `arg2`? – jlewkovich Jun 26 '19 at 23:31
  • @jlewkovich my favorite way is to pass undefined for arg2. When I write a function that has >1 optional parameters I include a check for them like `if(typeof arg2 ==='undefined'){//do something elegant}` But I think this can cause problems if the function writer used arguments.length to determine if an optional argument is present. I personally would only use that if I had a single optional parameter, which I would put at the end. More detail here: https://stackoverflow.com/a/11783117/10043754 – Chris Walker Jul 13 '21 at 17:04
0

I made a work around for what I was previously requesting, here's my system:

// ------------------------------------------------------------------------------------------------- Event "Class"
Event = function() {
    var
        Public = this,
        Private = {}
    ;

    Public.Create = function(Name) {
        if(Private.Created) {
            return false;
        }

        Private.Created = true;
        Private.Name = Name;
        Private.Function = [];
        return true;
    }

    Public.Delete = function() {
        if(! Private.Created) {
            return false;
        }

        Private = {};
        Private.Created = false;
        return true;
    }

    Public.IsCreated = function() {
        if(! Private.Created) {
            return false;
        }
        return true;
    }

    Public.SetName = function(Name) {
        if(! Private.Created) {
            return false;
        }

        Private.Name = Name;
        return true;
    }

    Public.GetName = function() {
        var
            Name = ""
        ;

        if(! Private.Created) {
            return Name;
        }

        Name = Private.Name;
        return Name;
    }

    Public.AddFunction = function(Function) {
        if(! Private.Created) {
            return false;
        }

        for(var FunctionID = 0, Length = Private.Function.length; FunctionID < Length; FunctionID++) {
            if(Private.Function[FunctionID] == Function) {
                return false;
            }
        }

        Private.Function[Private.Function.length] = Function;
        return true;
    }

    Public.HasFunction = function(Function) {
        if(! Private.Created) {
            return false;
        }

        for(var FunctionID = 0, Length = Private.Function.length; FunctionID < Length; FunctionID++) {
            if(Private.Function[FunctionID] == Function) {
                return true;
            }
        }
        return false;
    }

    Public.Call = function() {
        if(! Private.Created) {
            return false;
        }

        var 
            Arguments = ""
        ;

        for(var argumentID = 0, Length = arguments.length; argumentID < Length; argumentID++) {
            Arguments += "arguments[" + argumentID + "]";

            if(argumentID != (arguments.length - 1)) {
                Arguments += ", ";
            }
        }

        for(var FunctionID = 0, Length = Private.Function.length; FunctionID < Length; FunctionID++) {
            eval("Private.Function[FunctionID](" + Arguments + ")");
        }
        return false;
    }

    Public.Create(arguments[0]);
    return Public;
}

var
    TestEvent = new Event("TestEvent")
;

TestEvent.AddFunction(
    function() {
        console.log("TestEvent called.");
    }
);

TestEvent.AddFunction(
    function(String, String1) {
        console.log(String1 + String);
    }
);

TestEvent.Call("world!", "Hello ");

This works flawlessly. I've ran many benchmark tests.