title: Cross browser support for get and set properties
body: <p>My goal is to implement get and set properties on Javascript objects.</p>
  
  <p><code>Object.defineProperty</code> seems to be supported in IE9+ on a non DOM <code>Object</code>. I want it to work down to IE7.</p>
  
  <p><code>__defineGetter__</code> is <a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineGetter" rel="nofollow noreferrer">deprecated</a></p>
  
  <p>There seems to be some <a href="http://johndyer.name/native-browser-get-set-properties-in-javascript/" rel="nofollow noreferrer">workarounds</a> aka "hacks":</p>
  
  <pre><code>// 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);
  
      }
  }
  
  // must be a DOM object (even if it's not a real tag) attached to document
  var myObject = document.createElement('fake');
  document.body.appendChild(myObject);
  
  // create property
  myObject.firstName = 'John';
  myObject.lastName = 'Dyer';
  addProperty(myObject, 'fullname',
      function() {
          return this.firstName + ' ' + this.lastName;
      },
      function(value) {
          var parts = value.split(' ');
          this.firstName = parts[0];
          this.lastName = (parts.length &gt; 1) ? parts[1] : '';
      });
  
  console.log(myObject.fullname); // returns 'John Dyer'
  </code></pre>
  
  <p><a href="http://ejohn.org/blog/javascript-getters-and-setters/" rel="nofollow noreferrer">Another alternative by John Resig</a></p>
  
  <p>I'm not a fan of the code above due to the DOM element part. Are there any "better" options as of today? Most of the posts that I've found on this subject are at least one year old.</p>
  
  <p><a href="https://stackoverflow.com/questions/9106936/cross-browser-getter-and-setter">Similar SO thread</a> </p>