Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8913681
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 15, 20262026-06-15T04:31:26+00:00 2026-06-15T04:31:26+00:00

I am working on a pretty ugly library that lets you do some strange

  • 0

I am working on a pretty ugly library that lets you do some strange things.
Having a graph you can map a set of collections in a chain-like style and when you alter a
value to be altered in the whole system.

The problem came when the end type is a JS primitive.

In my case after making the graph with the values and objects I can do something like this:

CHAIN.components[0].value = 20; 

components is a filter function over the graph’s nodes using setters and getters.
If there is only one node filtered in components the default value set by the user would be available without doing this:
CHAIN.components.value = 20;
But rather this:
CHAIN.components = 20;

Now the problem is that the node could have other methods or properties besides a default ( which in my case is set on value.

How can i use the setters and getters on Number object without hacking in the Number.prototype, because CHAIN.components is now a Number ( if it’s not a primitive i’ve made it work in an unobtrusive way ), but when i want to call the CHAIN.components.func() there is a problem because i would have to append to the Number.prototype the func every time i make a set or get on the components and then delete it.

Do you have another idea for accomplishing this kind of behavior?

You wanted code so here it is:

/*jslint nomen: true, sloppy: true*/
GRID.modules.OHM || Object.extend(GRID.modules, ( function() {
    var Node, Nodes, Ohm, num_proto = Number.prototype.__clone(), str_proto = String.prototype.__clone();
    Node = function(uid) {
        var UID = uid;
        this.getUID = function() {
            return UID;
        };
    };
    Nodes = function() {
        var stack = [];
        this.add = function(id, val) {
            var n = new Node(stack.length);
            val.id = id;
            Object.extend(n, val);
            stack.push(n);
            return n.getUID();
        };
        this.getById = function(id) {
            return stack.filter(function(v) {
                var a = id || v.id;
                return (v.id === a);
            });
        };
        this.getByUID = function(UID) {
            return stack[UID];
        };
        this.get = function(callback) {
            !Object.isString(callback) || ( callback = [callback]);
            var f = Object.isFunction(callback) ? callback : (Object.isArray(callback) ? function(k) {
                return (callback.indexOf(k.id) >= 0);
            } : function(k) {
                return true;
            });
            return stack.filter(f);
        };
    };
    Ohm = function(n) {
        var graph = n || (new Nodes()), filters = {}, __nodes = {}, addGS = function(obj, name, conf, binder) {
            var alfa = {};
            Object.extend(alfa, conf);
            if (!alfa.get) {
                alfa.get = function() {
                    var a = this.g.getById(this.p);
                    return a.length === 1 ? a[0] : a;
                }.bind(binder);
            } else {
                alfa.get = alfa.get.bind(binder);
            }
            if (!alfa.set) {
                alfa.set = function(value) {
                    this.g.getById(this.p).forEach(function(k) {
                        Object.extend(k, value);
                        return true;
                    });
                }.bind(binder);
            } else {
                alfa.set = alfa.set.bind(binder);
            }
            Object.defineProperty(obj, name, alfa);
        }, add = function(id, node) {
            if (__nodes.hasOwnProperty(id)) {
                addGS(__nodes, id, {
                    enumerable : true
                }, {
                    t : this,
                    p : id,
                    g : graph
                });
            }
            return graph.add(id, node || {});
        };
        Object.extend(this, {
            add : function() {
                add.apply(this, arguments);
            },
            map : function(name, f, that) {
                var n = name, filterer = ['add', 'map', '__all'];
                n = Object.isFunction(n) ? name.apply(that, arguments.slice(3)) : n;
                if (filterer.indexOf(n.toLowerCase()) >= 0) {
                    console.log("You can't map over a basic property of object !!! Please read the freakin' manual.");
                    return null;
                }
                if (!filters.hasOwnProperty(n)) {
                    filters[n] = new Ohm(graph);
                    addGS(this, n, {
                        get : function() {
                            this.g.get(this.f).forEach(function(v, key, arr) {
                                var temp, binder;
                                if (arr.length !== 1) {
                                    if (!this.filt.hasOwnProperty(v.id)) {
                                        addGS(this.filt, v.id, {
                                            set : function(value) {
                                                this.t.g.getById(this.p).filter(this.t.f).forEach(function(k) {
                                                    Object.extend(k, value);
                                                });
                                            },
                                            get : function() {
                                                var a = this.t.g.getById(this.p).filter(this.t.f);
                                                return a.length === 1 ? a[0] : a;
                                            }
                                        }, {
                                            t : this,
                                            p : v.id
                                        });
                                        (key !== arr.length - 1) || Object.extend(this.filt, this.g.get(this.f));
                                    }
                                } else {
                                    if (Object.isFunction(v.__new__)) {
                                        v.__default = function() {
                                            return Object.extend((new this.__new__(arguments)), this);
                                        };
                                    }
                                    if (!Object.isUndefined(v.__default)) {
                                        temp = this.filt;
                                        this.filt = Object.isFunction(v.__default) ? v.__default.bind(v) : v.__default;
                                        if (Object.isNumber(this.filt) || Object.isString(this.filt)) {
                                            var prot = Object.isNumber(this.filt) ? Number : String;
                                            for (var i in temp) {
                                                if (temp.hasOwnProperty(i) && !prot.prototype.hasOwnProperty(i)) {
                                                    var bin = {
                                                        t : temp,
                                                        m : i,
                                                        p : prot,

                                                    };
                                                    Object.defineProperty(prot.prototype, i, {
                                                        set : function(value) {
                                                            Object.defineProperty(this.p.prototype, this.m, {
                                                                configurable : true, // defaults to false
                                                                writable : false,
                                                                value : 1
                                                            });
                                                            delete this.p.prototype[this.m];
                                                            this.t[this.m] = value;
                                                        }.bind(bin),
                                                        get : function() {
                                                            Object.defineProperty(this.p.prototype, this.m, {
                                                                configurable : true, // defaults to false
                                                                writable : false,
                                                                value : 1
                                                            });
                                                            delete this.p.prototype[this.m];
                                                            return this.t[this.m];
                                                        }.bind(bin),
                                                        enumerable : true,
                                                        configurable : true
                                                    });
                                                }
                                            }
                                        } else {
                                            Object.extend(this.filt, temp);
                                        }
                                    }
                                    if (Object.isNumber(this.filt) || Object.isString(this.filt)) {
                                        var prot = Object.isNumber(this.filt) ? Number : String;
                                        for (var i in v) {
                                            if (v.hasOwnProperty(i) && !prot.prototype.hasOwnProperty(i)) {
                                                var bin = {
                                                    t : v,
                                                    m : i,
                                                    p : prot,

                                                };
                                                Object.defineProperty(prot.prototype, i, {
                                                    set : function(value) {
                                                        Object.defineProperty(this.p.prototype, this.m, {
                                                            configurable : true, // defaults to false
                                                            writable : false,
                                                            value : 1
                                                        });
                                                        delete this.p.prototype[this.m];
                                                        this.t[this.m] = value;
                                                    }.bind(bin),
                                                    get : function() {
                                                        Object.defineProperty(this.p.prototype, this.m, {
                                                            configurable : true, // defaults to false
                                                            writable : false,
                                                            value : 1
                                                        });
                                                        delete this.p.prototype[this.m];
                                                        return this.t[this.m];
                                                    }.bind(bin),
                                                    enumerable : true,
                                                    configurable : true
                                                });
                                            }
                                        }
                                    } else {
                                        Object.extend(this.filt, v);
                                    }
                                }
                            }, this);
                            return this.filt;
                        },
                        set : function(value) {
                            this.g.get(this.f).forEach(function(k) {
                                Object.extend(k, value);
                            });
                        }
                    }, {
                        t : this,
                        f : f,
                        g : graph,
                        filt : filters[n]
                    });
                }
            }
        }, true, true);
        addGS(this, '__all', {
            get : function() {
                var a = this.g.getById();
                Object.extend(__nodes, a.length === 1 ? a[0] : a);
                return __nodes;
            },
            enumerable : true
        }, {
            t : this,
            p : null,
            g : graph
        });
    };
    window['Ω'] = Ohm;
    return {
        OHM : Ohm,
    };
}()));

And now the demo:

var c = new Ω();
c.add('ann', {
__default : 58,
blah : 98,
ceva : function()
{
    console.log('asd');
}
});
c.add('ann2',{
    __default: function(){
       console.log('hello');
    },
    abc: 78,
    dce: function(){
       console.log(' world');
    }
};
c.add('b2', {
__new__ : function() {
    this.init = function() {
        this.id = 86;
    };
    this.mer = function() {
        console.log(this);
    };
},
els : 'asadar'
});
c.map('b2', function(k) {
return k.id === 'b2';
});
c.map('ann', function(k) {
return k.id === 'ann';
});
c.map('ann2', function(k) {
return k.id === 'ann2';
});
console.log(c.ann); // returns 58 ( the __default value )
console.log(c.ann.blah); // returns 98
console.log(c.ann.blah.blah); // undefined
console.log(c.ann2);  // function()
c.ann2(); // prints out 'hello'
c.ann2.cde(); // prints out 'world'
c.ann2 = 60;
console.log(c.ann2); // 60
console.log(c.ann2.cde()); // prints out 'world'

This code works, but the part where i have to use the Number or String prototype bothers me. Do you have another way of doing this?

The reason is to do something that someone said it could be done in PHP but not JS, this guy had recently been working with me on WebGL shaders and hated that he had to write 700 lines of code to use multiple effect combined with FBO instead of 100 which would took him with a similar tool like this one which was written in PHP. So yes i KNOW the accessors on primitive prototypes is a hack but how can i make it different without having to use valueOf if the chain end object is a primitive?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-15T04:31:27+00:00Added an answer on June 15, 2026 at 4:31 am

    OK, now I’ve read the attached code (but could not follow all of it). Lacks some comments, but I won’t bitch about that, my own codes are not better as I don’t expect anybody to read or understand them 🙂

    You are right, the part where you extend the native prototypes is scary. From what I understand, you define an accessor property on the Number or String prototype before returning a number / string. Both on getting and setting, the accessor property is overwritten by a data property (???), then the whole property is deleted, before you store / return the value. This seems to be a clever hack to allow custom properties on primitive values, yet:

    • There is a high risk of collisions. It might be possible to lower that by using the this value as a key in a lookup table (to differentiate (5).x from (3).x), but it still can’t be fully avoided.
    • Properties that remove themselves on accessing / setting are extremely unintuitive. Avoid that.
    • arbitrarily changing accessor properties on the prototype of primitives are costly. That’s 4 performance-contras combined. No engine will be able to optimize this. And you seem to use them quite often.

    If you really needed this (I still didn’t get your reason), I’d use a variant with a lookup-table. It should reduce collisions (not sure how your code handled them), does not change the accessor properties ones they’re defined and is therefore more persistent (though it might leak then):

    // Let's call this
    // PRIMITIVE PROXIES
    // as they proxy real objects behind primitive values
    var proxy = _.map( { // some map that works on Objects
        string: String.prototype,
        number: Number.prototype
    }, function closure(type, proto) {
        var table = {};
        function setupProperty(prop) {
            if (prop in proto) return; // ah, we already proxied this kind of object
            Object.defineProperty(proto, prop, {
                configurable:true, // for deleting
                get: function getter() {
                    // "this" is the primitive value
                    if (!this in table)
                        return undefined;
                    return table[this][prop]; // get prop from obj
                },
                set: function setter(val) {
                    if (this in table)
                        table[this][prop] = val; // pass val to obj
                }
            });
        }
        return {
            create: function createProxy(prim, obj) {
                if (prim in table) // we already did create a proxy on this primitive
                    return; // let's abort. You might continue to overwrite
                table[prim] = obj;
                Object.getOwnPropertyNames(obj).forEach(setupProperty);
                return prim; // the new "proxy"
            },
            move: function moveName(from, to) {
                if (to in table) return false;
                table[to] = table[from];
                delete table[from];
                return true;
            }
        };
    });
    proxy.create = function(prim, obj) {
        return proxy[typeof prim].create(prim, obj);
    };
    proxy.move = function(from, to) {
        return proxy[typeof from].create(from, to);
    };
    // USAGE:
    // proxy.create works just like Object.extend
    > var c = {ann: 58},
    >     o = {blah: 98};
    > proxy.create(c.ann, o);
    > 58..blah
    98
    > c.ann.blah
    98
    > (58).blah = 60;
    > o
    {blah: 60}
    > var num = c.ann; // 58
    > c.ann.blah = function(){return "Hello"};
    > num.blah()
    "Hello"
    > proxy.move(c.ann, c.ann = 78);
    > c.ann
    78
    > (58).blah
    undefined
    > c.ann.blah()
    "Hello"
    > // getters/setters for properties are global:
    > c.ann.blub = "something"; // does not work, there is no getter
    > c.ann.blub
    undefined
    > proxy.create(58, {blub: "foo"})
    > c.ann.blub // still returns
    undefined
    > c.ann.blub = "bar"; // but can be set now
    > (58).blub + (78).blub
    "foobar"
    > // infinite lookup loops are possible:
    > proxy.create("loop", {x:"loop"});
    > "loop" === "loop".x
    true
    > "loop".x.x.x.….x
    "loop"
    

    However, there is one thing you will never be able to work around:

    Unlike objects, primitive values are not unique; they have no identity.

    You will never be able to distinguish c.ann from 58, or "loop" from "loop".x, and so both will have a property or not. This is not a good premise to build an API upon.

    So, I still recommend to use Number and String objects. You don’t need to subclass them (as shown in my previous answer), as you don’t seem to have (m)any methods on them, so you can easily build them:

    c.ann = new Number(58);
    c.ann.blah = 98;
    return c;
    

    There should be hardly a difference, expect for the typeof operator. Could you maybe add some more examples that use the __default value?

    but how can I make it different without having to use valueOf if the chain end object is a primitive?

    To answer this simple question: That guy was right, it cannot be done in JavaScript without hacking native prototypes. And you are right, the hack is quite ugly 🙂

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I got some radio controls that in JQuery Mobile 1.0.1 (stable) were working pretty
I've got an app that's working pretty flawlessly in Chrome and FF, however, when
I'm working on some middleware for rails, working with a pretty recent version: pfernand-2-mn:~
I have a very strange situation. I´m working on a pretty big Java application
I'm still working my way through some pretty basic Actionscript programming (in Flex), and
Core Data is working pretty smoothly in my app. I can store and retrieve
My css3 animated menu is working pretty well. But now i want to add
I am working on a pretty simple web application (famous last words) and am
I'm working on a pretty simple Java app in order to learn more about
I'm working on a pretty complex web application in Ext with Google maps API

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.