“对象不支持此属性或方法”IE10 / 11

时间:2017-09-05 14:41:40

标签: javascript internet-explorer

随着ES6的采取,我渴望放弃jQuery并使用本机JS为我的网站构建保持快速和轻量级。也是为了提高我的JS技能,因为我是那些直接使用jQuery的人之一。

我正在构建一个小小的库,以便在函数中使用更常用的javascript来保持文件的小。

function $(elm) {
    var elm = document.querySelectorAll(elm);

    this.forEach = function(f) {
        [].forEach.call(elm, f);
    }

    return elm;
}

function slider() {
    $(".slider").forEach(function() {
        alert("Hello");
    });
}
slider();

这在Chrome等中效果很好..但在IE10 / 11中我收到了错误

  

Object不支持此属性或方法“forEach”

引用$(“。slider”)。forEach

有什么想法吗?

1 个答案:

答案 0 :(得分:4)

您将forEach添加到window对象,而不是添加到您返回的对象;你将$称为函数,而不是构造函数。由于您使用松散模式(显然),函数调用中的this是对全局对象的引用(在浏览器上也可以作为window访问)。您将querySelectorAll的集合保持不变。

它在Chrome上运行的原因是querySelectorAll返回的集合有自己的forEach(这是一个相当新的补充)。

为此,有四个选项:

  1. 返回一个对象并向其添加forEach,将元素从QSA集合复制到该对象。 E.g:

    function $(selector) {
        const result = Array.from(document.querySelectorAll(selector));
        result.forEach = Array.prototype.forEach;
        // Perhaps map, filter, etc.; add in a loop?
        return result;
    }
    

    或者在ES5中:

    var $ = (function() {
        var methods = Array.prototype;
        function $(selector) {
            var result = methods.slice.call(document.querySelectorAll(selector));
            result.forEach = methods.forEach;
            // Perhaps map, filter, etc.; add in a loop?
            return result;
        }
        return $;
    })();
    
  2. forEach添加到NodeList原型(如果它尚未存在)并直接在forEach的集合中使用querySelectorAll。例如:

    if (typeof NodeList !== "undefined" &&
        NodeList.prototype &&
        !NodeList.prototype.forEach) {
        // Yes, direct assignment is fine here, no need for `Object.defineProperty`
        NodeList.prototype.forEach = Array.prototype.forEach;
    }
    

    (上面不需要Object.definePropertyenumerable [令人惊讶],configurablewritable在Chrome和Firefox上都是true,所以我们可以像上面那样直接分配。)

    ...当然,你的$只不过是

    function $(selector) {
        return document.querySelectorAll(selector);
    }
    

    (首先。如果你想添加更多功能,你可能想要采用#1的方式。)

  3. 返回一个数组:

    function $(selector) {
        return Array.from(document.querySelectorAll(selector));
    }
    

    或者在ES5中:

    function $(selector) {
        return Array.prototype.slice.call(document.querySelectorAll(selector));
    }
    
  4. 子类Array(无法在ES2015之前的JavaScript引擎上完全填充),因此您可以在Array的功能之上添加自己的功能:

    class MyThingy extends Array {
        // Perhaps further methods here
    }
    function $(selector) {
        return MyThingy.from(document.querySelectorAll(selector));
    }
    

    此处没有ES5选项,您至少需要进行转换和填充。

  5. 如果您要添加Array提供的功能以外的其他功能,我非常喜欢#4,而不仅仅是填充#34;所以"好。它可能足以满足您的目的。