Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript equivalent of C#'s DynamicObject?

Tags:

javascript

c#

Just to be clear, a class that inherits DynamicObject (in C# of course) is not the same concept as JavaScript's variables being dynamic. DynamicObject allows the implementer to programmatically determine what members an object has, including methods.

Edit: I understand that JavaScript objects can have any members added to them at run time. That's not at all what I'm talking about. Here's a C# example showing what DynamicObject does:

public class SampleObject : DynamicObject
{
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = binder.Name;
        return true;
    }
}

dynamic obj = new SampleObject();
Console.WriteLine(obj.SampleProperty);
//Prints "SampleProperty".

When a member of obj is accessed, it uses the TryGetMember to programmatically determine whether the member exists and what its value is. In short, the existence of a member is determined when it's requested, not by adding it before hand. I hope this clarifies the question a little. In case you're wondering, I'm trying to determine if it's possible to make an object in JavaScript, that when the function call syntax is used on it like so:

myAPI.uploadSomeData(data1, data2)

The uploadSomeData call goes to a "TryGetMember" like function, which performs an $.ajax call using the name "uploadSomeData" to generate the URL, and the return value is the result.

like image 366
Brent Avatar asked Oct 06 '22 19:10

Brent


2 Answers

Amazing the after only a few weeks of occasional JavaScript studies I've managed to find two answers:

ES6 Proxies

noSuchMethod

like image 119
Brent Avatar answered Oct 11 '22 06:10

Brent


JavaScript allows to iterate through object's properties and methods in for...in loop. You can determine is it a method using typeof operator.

HTML:

<ul id="console"></ul>​

JavaScript:

var Application = (function(app) {
    app.constants = app.constants || {};
    app.constants.PRINT_OBJ_TITLE = '[Printing an object]';

    app.console = {
        constants: {
            SEPARATOR: new Array(50).join('-')
        },
        output: document.getElementById('console'),
        log: function() {
            var li = document.createElement('li');
            li.innerHTML = Array.prototype.join.call(arguments, '');
            this.output.appendChild(li);
        },
        printSeparator: function() {
            this.log(this.constants.SEPARATOR);
        }
    };

    app.printObj = function(obj) {
        this.console.log(app.constants.PRINT_OBJ_TITLE);
        for(var prop in obj) {
            if(obj.hasOwnProperty(prop)) {
                var propType = (typeof obj[prop] == 'function')
                    ? 'function'
                    : 'property';
                this.console.log(propType, ': ', prop);
            }
        }
        this.console.printSeparator();
    };

    return app;
})(Application || {});


var obj = {},
    app = Application;

obj.foo = function() {
    alert("I'm a foo function!");
};

obj.bar = "I'm just a property";

app.printObj(obj);​

DEMO

UPDATE

So you should not expect from JavaScript such a lot of reflection tools as Java or C# have. You can emulate such behavior in some way, but anyway you'll not be able to just create your special JavaScript object and call its non-existing property. The only way is to create a special functions which will implement switches, facades, maps, etc. - any constructions that allows to make the flow more dynamic.

Something like this exmaple.

You can improve this logic and add additional properties and functions to that app.Stuff on-the-fly depending to user's actions, incoming data, etc. So overall you can build smart and flexible system using some kind of meta-programming in JavaScript.

like image 26
Eugene Naydenov Avatar answered Oct 11 '22 06:10

Eugene Naydenov