【问题标题】:JavaScript getter support in IE8IE8 中的 JavaScript getter 支持
【发布时间】:2011-12-09 03:04:30
【问题描述】:

查看此代码。这是一个非常简单的 JavaScript 对象,使用 Module Pattern 实现(您可以在 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);

但是,IE8 不支持 JavaScript getset 关键字。你可以测试它并查看MDN

我应该怎么做才能使这个脚本也与 IE8 兼容?

【问题讨论】:

    标签: javascript internet-explorer-8 setter getter javascript-objects


    【解决方案1】:

    我应该怎么做才能使这个脚本也与 IE8 兼容?

    彻底改变它。例如,不要使用访问器属性,而是使用普通属性和函数的组合:

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

    其他人建议在 IE 中使用 DOM 对象并使用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
    

    至少 Chrome 是这样。无论哪种方式,编写适用于您想要支持的所有浏览器的代码都更安全、更容易。您从编写代码以利用 getter 和 setter 获得的任何便利都已在您专门针对 Internet Explorer 8 编写的额外代码中丢失了。

    当然,除了性能下降之外,您将无法在对象上使用for...in 循环,以及当您使用您认为自己定义的属性时随之而来的潜在混淆,但已在 DOM 对象上预先存在。

    【讨论】:

    • 我的意思是如何使我的代码向后兼容。在 JavaScript 中实现模块模式的解决方案是什么,它也适用于 IE8,并且具有 getter 属性?
    • @SaeedNamati 如果你真的想要 getter/setter,你可以做两件事:1) 制作诸如 .getMyValue.setMyValue 之类的方法,或者 2) 制作接受值或返回的方法如果没有给出值(就像 jQuery 对某些方法所做的那样 - 如果你给出它设置的值,如果你不给出它得到的值)。
    • @DontVoteMeDown:很抱歉你有这种感觉,但我敢肯定还有更糟糕的答案。你知道,比如不正确的答案;-)。
    • @BT:不,这不正确。我的回答指出'不可能在非 DOM 对象上使用 getter 和 setter'。请您告诉我您是如何发现这是不正确的,因为您的回答只能证明它是正确的。
    • @BT:撇开您试图将您的阅读理解能力差归咎于我的回答中的措辞,我想指出,OP 很高兴接受这个答案,虽然我可以已经推广了您自己的答案中指出的不良做法,我觉得这是没有自尊的 JavaScript 开发人员会使用的解决方案,更不用说鼓励其他人使用了。有时,“我将不得不以其他方式解决这个问题”这种严酷的认识对每个人来说都是最好的。
    【解决方案2】:

    你不能(as Andy answered

    最接近的选择是

    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/的演示

    【讨论】:

    • IE 总是很糟糕。虽然微软有很多好产品,但我真的很讨厌微软,只是因为它的IE。
    • @Saeed:真的,这是不是微软的错的一种情况。 Getter 和 setter 是最近添加到 ECMA-262 规范中的。 IE 9 通过Object.defineProperty() 支持getter 和setter。您正在使用的实现(Mozilla 的)是非标准的,并且不能保证在许多浏览器中都能正常工作。
    • 但是@Gaby,Firefox 从 2.0 版开始支持,Chrome 从 1 版开始,Safari 从 3.5 版开始,Opera 从 9.5 版开始。那么,IE8怎么不支持这种东西呢?
    • @Saeed:与 Firefox 不支持 element.innerTextbackground-position-x 或 Chrome 和其他浏览器长期以来支持的许多其他 Internet Explorer 专有功能的原因相同。
    【解决方案3】:

    查看http://robertnyman.com/2009/05/28/getters-and-setters-with-javascript-code-samples-and-demos/

    扩展对象的未来和 ECMAScript 标准化方式 各种方式都是通过Object.defineProperty。这是如何 Internet Explorer 选择实现 getter 和 setter,但它是 不幸的是,目前仅在 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"
    

    【讨论】:

    • 更正了结果。
    【解决方案4】:

    IE8 支持 DOM 节点上的 getter 和 setter,所以如果你真的想拥有 getter 和 setter,你可以这样做:

    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 上使用这种技术,你就是金子:)

    【讨论】:

    • 这种方法存在几个问题,使其过于复杂且不值得。例如,原型继承超出了窗口,您提到的对象创建性能问题,可能的命名冲突等等。它远非“黄金”。
    • 虽然不是一个黄金解决方案(使用 IE 的可能性很大),但它确实回答了这个问题......
    • 谢谢。我所需要的只是一个紧凑而简单的类来在会话期间存储/检索值。这让我可以在需要时轻松声明和使用属性。
    • 这是 IE 8 的一个很好的解决方法,并且是在非 DOM 对象上使用该浏览器执行本机 getter/setter 的唯一真正方法。在紧要关头工作得很好,尽管它不是跨平台的,除非你让每个浏览器都使用相同的技术和相同的限制。否则,您需要使用单独的“object”和“objectForIe8”,这会在不使用自定义 get/set 函数的情况下破坏最初的尝试。换句话说,任何试图让一个优雅的、通用的函数以这种方式工作的人都不要打扰;我试过了。
    猜你喜欢
    • 1970-01-01
    • 2011-06-17
    • 1970-01-01
    • 2011-11-13
    • 2016-08-13
    • 2011-07-29
    • 1970-01-01
    • 2013-05-30
    • 2013-08-03
    相关资源
    最近更新 更多