JavaScript getter support in IE8
Asked Answered
P

4

13

Check out this code. This is a very simple JavaScript object which is implemented using Module Pattern (and you can see the live example at this fiddle address)

var human = function() {
    var _firstName = '';
    var _lastName = ''
    return {
        get firstName() {
            return _firstName;
        }, get lastName() {
            return _lastName;
        }, set firstName(name) {
            _firstName = name;
        }, set lastName(name) {
            _lastName = name;
        }, get fullName() {
            return _firstName + ' ' + _lastName;
        }
    }
}();
human.firstName = 'Saeed';
human.lastName = 'Neamati';
alert(human.fullName);

However, IE8 doesn't support JavaScript get and set keywords. You can both test it and see MDN.

What should I do to make this script compatible with IE8 too?

Preparation answered 17/10, 2011 at 8:39 Comment(0)
I
24

What should I do to make this script compatible with IE8 too?

Change it completely. For example, instead of using accessor properties, use a combination of normal properties and functions:

human.firstName = 'Saeed';
human.lastName  = 'Neamati';
alert(human.getFullName());

Somebody else suggested using a DOM object in IE and adding the properties using Object.defineProperty(). While it may work, I'd highly recommend against this approach for several reasons, an example being that the code you write may not be compatible in all browsers:

var human = document.createElement('div');
Object.defineProperty(human, 'firstName', { ... });
Object.defineProperty(human, 'lastName',  { ... });
Object.defineProperty(human, 'children',  { value: 2 });

alert(human.children);
//-> "[object HTMLCollection]", not 2

This is true of at least Chrome. Either way it's safer and easier to write code that works across all the browsers you want to support. Any convenience you gain from being able to write code to take advantage of getters and setters has been lost on the extra code you wrote specifically targeting Internet Explorer 8.

This is, of course, in addition to the reduction in performance, the fact that you will not be able to use a for...in loop on the object and the potential confusion ensuing when you use a property you thought you defined but was pre-existing on the DOM object.

Inflorescence answered 17/10, 2011 at 8:51 Comment(6)
I meant how can I make my code backward compatible. What is the solution to implement a module pattern in JavaScript that works in IE8 also, and which has getter properties?Preparation
@SaeedNeamati If you really want getters/setters, you can do two things: 1) make methods such as .getMyValue and .setMyValue, or 2) make methods that accept a value, or return it if no value given (like what jQuery does with some methods - if you give a value it sets, if you don't give a value it gets).Quoin
@DontVoteMeDown: I'm sorry you feel that way, but I'm sure there are worse answers. You know, like answers that are incorrect ;-).Inflorescence
@BT: no, it's not correct. My answer states that 'it's not possible to have getters and setters on non DOM objects'. Please can you tell me how you have found that to be incorrect, because your answer only proves it to be true.Inflorescence
I suppose I misread your answer as "its not possible period" because its poorly written to convey that it is possibly to use accessors on DOM objects. My answer tells him how to "make this script compatible with IE8 too", but yours does not.Calves
@BT: setting aside your attempt at blaming your poor reading comprehension on the wording in my answer, I'd like to point out that the OP was happy enough to accept this answer and, whilst I could have promoted the bad practice indicated in your own answer, I feel that is a solution no self-respecting JavaScript developer would ever use, let alone encourage others to. Sometimes the harsh realisation of "I'll have to approach this some other way" is best for everyone.Inflorescence
B
8

You cannot (as Andy answered)

The closest alternative would be

var human = function() {
    var _firstName = '';
    var _lastName = '';

    return {
        firstName: function() {
            if (arguments.length === 1) {
                _firstName = arguments[0];
            }
            else {
                return _firstName;
            }
        },
        lastName: function() {
            if (arguments.length === 1) {
                _lastName = arguments[0];
            }
            else {
                return _lastName;
            }
        },
        fullName: function() {
            return _firstName + ' ' + _lastName;
        }
    };
}();

human.firstName('Saeed');
human.lastName('Neamati');

alert(human.fullName());

Demo at http://jsfiddle.net/gaby/WYjqB/2/

Beset answered 17/10, 2011 at 9:10 Comment(4)
IE always sucks. Though Microsoft has many good products, but I truly hate Microsoft, only because of its IE.Preparation
@Saeed: really, this is one scenario where it isn't Microsoft's fault. Getters and setters are a recent addition to the ECMA-262 specification. IE 9 supports getters and setters via Object.defineProperty(). The implementation you're using (Mozilla's) is non-standard and not guaranteed to work in many browsers anyway.Inflorescence
But @Gaby, Firefox has supported this from version 2.0, Chrome from version 1, Safari from version 3.5, and Opera from version 9.5. So, how is that, that IE8 can't support such a thing?Preparation
@Saeed: the same reason Firefox doesn't support element.innerText or background-position-x or many other proprietary features of Internet Explorer that Chrome and other browsers have supported for a long time.Inflorescence
C
5

IE8 supports getters and setters on DOM nodes, so if you really want to have getters and setters, you can do this:

var objectForIe8 = $("<div></div>")[0];    
Object.defineProperty(objectForIe8, "querySelector", {
    get: function() {
        return this.name;
    },
    set: function(val) {
        this.name = val+", buddy";  
    }
});
// notice you can overwrite dom properties when you want to use that property name
objectForIe8.querySelector = "I'm not your guy"; 

alert(objectForIe8.querySelector);

Note this gives you a somewhat significant performance hit, so I wouldn't use this technique if you need to create thousands of objects like this. But if you're not worried about performance of this particular object, it'll tide you over. And if you couldn't care less about ie8 performance, and just want it to work, use this technique for ie8 only and you're golden : )

Calves answered 8/7, 2013 at 22:17 Comment(4)
There are several problems with this approach that make it overly complicated and not really worth it. For example, prototypal inheritance goes out of the window, object creation performance issues that you mention, possible naming collisions, and so on. It's far from "golden".Inflorescence
While not being a golden solution (fat chance of that while using IE), it does in fact answer the question...Calves
Thanks. All I needed was a compact and simple class to store / retrieve values for the duration of the session. This made it easy for me to declare and use properties when needed.Kraft
This is a great workaround for IE 8, and the only real way to do a native getter/setter with that browser on non-DOM objects. Works well in a pinch, though it's not cross-platform unless you subject every browser to the same technique with the same limitations. Otherwise you need to use a separate "object" and "objectForIe8" which defeats the original attempt at convenience without resorting to custom get/set functions. In other words, anyone trying to get an elegant, universal function working this way, don't bother; I've tried.Plumose
M
4

Check it on http://robertnyman.com/2009/05/28/getters-and-setters-with-javascript-code-samples-and-demos/

The future, and ECMAScript standardized way, of extending objects in all sorts of ways is through Object.defineProperty. This is how Internet Explorer chose to implement getters and setters, but it is unfortunately so far only available in Internet Explorer 8, and not in any other web browser. Also, IE 8 only supports it on DOM nodes, but future versions are planned to support it on JavaScript objects as well.

You can find the test cases on the same site at http://robertnyman.com/javascript/javascript-getters-setters.html#object-defineproperty

Object.defineProperty(document.body, "description", {
    get : function () {
        return this.desc;
    },
    set : function (val) {
        this.desc = val;
    }
});
document.body.description = "Content container";

Result:

document.body.description = "Content container"
Misconstruction answered 21/11, 2012 at 8:27 Comment(1)
Corrected the result.Misconstruction

© 2022 - 2024 — McMap. All rights reserved.