Cross-browser Getter and Setter
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.
Related videos on Youtube
Comments
-
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 almost 12 yearsThanks @Tiddo, I cannot find an available page now, and pasted the code from my testing page.
-
the system over 11 years
// ...IE8 (must be a DOM object),
,// IE6-7 ... must be a real DOM object
-
billy over 10 yearsThis doesn't add a property for non-DOM objects... it doesn't answer the question.
-
Sukima over 10 yearsMakes me ask why Microsoft hates JavaScript developers. (hate, a term used to describe the unwillingness to not release / retire broken implementations).
-
Dai Bok about 10 yearslink is back: An easier read: johndyer.name/native-browser-get-set-properties-in-javascript
-
razzed over 7 yearsVery important: If you are using
Object.defineProperty
on a property in the global (window
) object but that property was not defined using thewindow
object, thenObject.defineProperty
will always throw aTypeError: 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 about 7 yearsThat's why they created Silverlight: out of pure sadistic hatred of the javascript they created.