Cross-browser Getter and Setter

12,230

Solution 1

Here is the workaround for IE6/7/8. I performed the test and it works very well!

Update: The link is broken, you can see the code of from my testing here:

    // Super amazing, cross browser property function, based on http://thewikies.com/
function addProperty(obj, name, onGet, onSet) {

    // wrapper functions
    var
        oldValue = obj[name],
        getFn = function () {
            return onGet.apply(obj, [oldValue]);
        },
        setFn = function (newValue) {
            return oldValue = onSet.apply(obj, [newValue]);
        };

    // Modern browsers, IE9+, and IE8 (must be a DOM object),
    if (Object.defineProperty) {

        Object.defineProperty(obj, name, {
            get: getFn,
            set: setFn
        });

    // Older Mozilla
    } else if (obj.__defineGetter__) {

        obj.__defineGetter__(name, getFn);
        obj.__defineSetter__(name, setFn);

    // IE6-7
    // must be a real DOM object (to have attachEvent) and must be attached to document (for onpropertychange to fire)
    } else {

        var onPropertyChange = function (e) {

            if (event.propertyName == name) {
                // temporarily remove the event so it doesn't fire again and create a loop
                obj.detachEvent("onpropertychange", onPropertyChange);

                // get the changed value, run it through the set function
                var newValue = setFn(obj[name]);

                // restore the get function
                obj[name] = getFn;
                obj[name].toString = getFn;

                // restore the event
                obj.attachEvent("onpropertychange", onPropertyChange);
            }
        };  

        obj[name] = getFn;
        obj[name].toString = getFn;

        obj.attachEvent("onpropertychange", onPropertyChange);

    }
}

Solution 2

There is a "definePropery" method that will essentially allow you to create accessor methods (getters/setters) on Objects without the need to invoke a function call like setProp() / getProp().

The syntax is a little weird but I've been able to get this to work on Firefox, Chrome, Safari and IE9.

Say I have JavaScript Object called "Person".

function Person()
{
 // set a default value //
    this.__name = 'John';
 // add getter & setter methods //
    Object.defineProperty(this, "name", {
        get: function() {
        // additional getter logic
            return this.__name;
        },
        set: function(val) {
            this.__name = val;
        // additional setter logic
        }
    });
}

var p = new Person();
console.log(p.name); // 'John'
p.name = 'Stephen';
console.log(p.name); // 'Stephen'

More info on Mozilla's site here.

Solution 3

You cannot, the syntax is not supported in browsers that did not implement it. Its going to be quite a while before you'll be able to use that syntax without having CBC problems. Be grateful IE6 is pretty much dead in North America.

Share:
12,230

Related videos on Youtube

ryanve
Author by

ryanve

graffing webmural.com and s9a.page

Updated on June 04, 2022

Comments

  • ryanve
    ryanve about 2 years

    This works in modern Chrome/Firefox/Opera but fails in IE8. Haven't tried it in IE9. How can I make this cross-browser compatible, including IE7+? (Fiddle here.)

    var foo = { 
        get test(){ return 'Works'; } 
    };
    
    // foo.test should be 'Works'
    

    I've seen some usage with __defineGetter__ but that threw an 'unrecognized method' error in IE8.

  • Mason Zhang
    Mason Zhang almost 12 years
    Thanks @Tiddo, I cannot find an available page now, and pasted the code from my testing page.
  • the system
    the system over 11 years
    // ...IE8 (must be a DOM object), , // IE6-7 ... must be a real DOM object
  • billy
    billy over 10 years
    This doesn't add a property for non-DOM objects... it doesn't answer the question.
  • Sukima
    Sukima over 10 years
    Makes me ask why Microsoft hates JavaScript developers. (hate, a term used to describe the unwillingness to not release / retire broken implementations).
  • Dai Bok
    Dai Bok about 10 years
  • razzed
    razzed over 7 years
    Very important: If you are using Object.defineProperty on a property in the global (window) object but that property was not defined using the window object, then Object.defineProperty will always throw a TypeError: Cannot redefine property on said property. See jsfiddle.net/marketacumen/03qpj13u for failure case, and jsfiddle.net/marketacumen/w2qjkc8s for success case (and workaround, if possible)
  • Admin
    Admin about 7 years
    That's why they created Silverlight: out of pure sadistic hatred of the javascript they created.