Поддержка геттера JavaScript в IE8

Проверьте этот код. Это очень простой объект JavaScript, реализованный с использованием шаблона модуля (и вы можете см. живой пример по адресу этот скрипт)

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);

Однако IE8 не поддерживает ключевые слова JavaScript get и set. Вы можете протестировать его и посмотреть MDN.

Что мне сделать, чтобы этот скрипт был совместим и с IE8?


person Saeed Neamati    schedule 17.10.2011    source источник


Ответы (4)


Что мне сделать, чтобы этот скрипт был совместим и с IE8?

Измените его полностью. Например, вместо использования свойств доступа используйте комбинацию обычных свойств и функций:

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

Кто-то еще предложил использовать объект DOM в IE и добавить свойства, используя Object.defineProperty(). Хотя это может работать, я настоятельно рекомендую не использовать этот подход по нескольким причинам, например, код, который вы пишете, может быть совместим не со всеми браузерами:

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.

Это, конечно, в дополнение к снижению производительности, тому факту, что вы не сможете использовать цикл for...in для объекта и потенциальную путаницу, возникающую при использовании свойства, которое, как вы думали, вы определили, но которое ранее существовало на объекте. DOM-объект.

person Andy E    schedule 17.10.2011
comment
Я имел в виду, как я могу сделать свой код обратно совместимым. Каково решение для реализации шаблона модуля в JavaScript, который также работает в IE8 и имеет геттерные свойства? - person Saeed Neamati; 17.10.2011
comment
@SaeedNeamati Если вам действительно нужны геттеры/сеттеры, вы можете сделать две вещи: 1) создать такие методы, как .getMyValue и .setMyValue, или 2) создать методы, которые принимают значение или возвращают его, если значение не задано (например, что jQuery делает с некоторыми методы - если вы даете значение, которое оно устанавливает, если вы не даете значение, которое оно получает). - person Camilo Martin; 02.10.2012
comment
@DontVoteMeDown: мне жаль, что вы так себя чувствуете, но я уверен, что есть ответы и похуже. Вы знаете, любят ответы, которые неверны ;-). - person Andy E; 22.01.2014
comment
@BT: нет, это неправильно. В моем ответе говорится, что "невозможно иметь геттеры и сеттеры для не DOM-объектов". Пожалуйста, не могли бы вы рассказать мне, как вы обнаружили, что это неверно, потому что ваш ответ только доказывает, что это правда. - person Andy E; 24.01.2014
comment
Я полагаю, что неправильно истолковал ваш ответ как невозможный период, потому что он плохо написан, чтобы сообщить, что возможно использовать средства доступа к объектам DOM. Мой ответ говорит ему, как сделать этот скрипт совместимым с IE8, а ваш - нет. - person B T; 26.01.2014
comment
@BT: оставив в стороне вашу попытку обвинить формулировку в моем ответе в плохом понимании прочитанного, я хотел бы отметить, что ОП был достаточно счастлив, чтобы принять этот ответ, и, хотя я мог бы продвигать плохую практику, указанную в вашем собственный ответ, я чувствую, что это решение, которое ни один уважающий себя разработчик JavaScript никогда не использовал бы, не говоря уже о том, чтобы поощрять других. Иногда горькое осознание того, что мне придется подойти к этому как-то иначе, лучше для всех. - person Andy E; 27.01.2014

Вы не можете (как ответил Энди)

Ближайшей альтернативой будет

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());

Демо на http://jsfiddle.net/gaby/WYjqB/2/

person Gabriele Petrioli    schedule 17.10.2011
comment
IE всегда отстой. Хотя у Microsoft много хороших продуктов, но я искренне ненавижу Microsoft только из-за его IE. - person Saeed Neamati; 17.10.2011
comment
@Saeed: действительно, это один из сценариев, в котором Microsoft не виновата. Геттеры и сеттеры — это недавнее дополнение к спецификации ECMA-262. IE 9 поддерживает геттеры и сеттеры через Object.defineProperty(). Используемая вами реализация (Mozilla) нестандартна и в любом случае не гарантируется работа во многих браузерах. - person Andy E; 17.10.2011
comment
Но @Gaby, Firefox поддерживает это с версии 2.0, Chrome с версии 1, Safari с версии 3.5 и Opera с версии 9.5. Так как же так, что IE8 не может поддерживать такое? - person Saeed Neamati; 17.10.2011
comment
@Saeed: по той же причине Firefox не поддерживает element.innerText или background-position-x или многие другие проприетарные функции Internet Explorer, которые Chrome и другие браузеры долгое время поддерживали. - person Andy E; 17.10.2011

IE8 поддерживает геттеры и сеттеры на узлах DOM, поэтому, если вы действительно хотите иметь геттеры и сеттеры, вы можете сделать это:

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);

Обратите внимание, что это значительно снижает производительность, поэтому я бы не стал использовать эту технику, если вам нужно создать тысячи таких объектов. Но если вы не беспокоитесь о производительности этого конкретного объекта, это вас устроит. И если вас не волнует производительность ie8, и вы просто хотите, чтобы он работал, используйте эту технику только для ie8, и вы золоты :)

person B T    schedule 08.07.2013
comment
Есть несколько проблем с этим подходом, которые делают его чрезмерно сложным и не стоящим того. Например, прототипное наследование выходит за рамки, упомянутые вами проблемы с производительностью создания объектов, возможные коллизии имен и так далее. Это далеко не золото. - person Andy E; 24.01.2014
comment
Хотя это и не является золотым решением (большая вероятность этого при использовании IE), оно на самом деле отвечает на вопрос... - person B T; 26.01.2014
comment
Спасибо. Все, что мне было нужно, это компактный и простой класс для хранения/получения значений на время сеанса. Это упростило мне объявление и использование свойств при необходимости. - person gouderadrian; 14.02.2014
comment
Это отличный обходной путь для IE 8 и единственный реальный способ сделать собственный геттер/сеттер с этим браузером для объектов, отличных от DOM. В крайнем случае работает хорошо, хотя и не является кросс-платформенным, если только вы не применяете ко всем браузерам одну и ту же технику с одинаковыми ограничениями. В противном случае вам нужно использовать отдельный объект и objectForIe8, который побеждает первоначальную попытку удобства, не прибегая к пользовательским функциям получения/установки. Другими словами, любой, кто пытается получить элегантную универсальную функцию, работающую таким образом, не беспокойтесь; Я пытался. - person Beejor; 19.11.2015

Проверьте это на http://robertnyman.com/2009/05/28/getters-and-setters-with-javascript-code-samples-and-demos/

Будущее и стандартизированный ECMAScript способ расширения объектов всеми возможными способами — через Object.defineProperty. Именно так Internet Explorer решил реализовать геттеры и сеттеры, но, к сожалению, пока это доступно только в Internet Explorer 8, а не в каком-либо другом веб-браузере. Кроме того, IE 8 поддерживает его только на узлах DOM, но в будущих версиях планируется поддерживать его и на объектах JavaScript.

Тестовые примеры можно найти на том же сайте по адресу 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";

Результат:

document.body.description = "Content container"
person Bob Yang    schedule 21.11.2012
comment
Исправил результат. - person Bob Yang; 01.12.2014