【问题标题】:How can I prevent enumeration for polyfills in JavaScript?如何防止枚举 JavaScript 中的 polyfill?
【发布时间】:2014-02-05 14:01:06
【问题描述】:

我一直在向我们项目的主 JavaScript 文件添加一个 Array.indexOf() 填充。我从 devdocs.io 获取的:

if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function (searchElement , fromIndex) {
    var i,
        pivot = (fromIndex) ? fromIndex : 0,
        length;

    if (!this) {
      throw new TypeError();
    } 

    length = this.length;

    if (length === 0 || pivot >= length) {
      return -1;
    }

    if (pivot < 0) {
      pivot = length - Math.abs(pivot);
    }

    for (i = pivot; i < length; i++) {
      if (this[i] === searchElement) {
        return i;
      }
    }
    return -1;
  };
}

我需要这个,因为我们仍然必须支持 IE 8,但似乎在 IE 8 中,indexOf() 函数被添加为可枚举的。这意味着,它会在使用 for..in 循环遍历数组时出现,如下所示:

var a = [];
a[0]=123;
a[1]=456;
for(var value in a) {
    alert(value); // this even alerts "indexOf", if the polyfill above is loaded, and this is a big problem
}

是否可以使 polyfill “不可枚举”,以便我能够在 IE 8 中使用 Array.indexOf(),但它不会出现在 for..in 循环中?

【问题讨论】:

  • 我认为 for ... in ... 对数组来说不是一个好主意:stackoverflow.com/questions/500504/…
  • 这里的解决方案是停止使用for...in来迭代一个Array。请改用简单的for 循环。
  • 我无法改变我们的代码中有数百个 for..in 循环在数组上的事实。改变它们将是一项巨大的工作。不过,polyfill 并没有在代码中出现这么久,删除它会相对容易......如果没有其他方法,我将不得不这样做。
  • @PaulMa 将代码移到 Array.prototype 之外是否可以接受?这包括以不同的方式称呼它。
  • 我一直在和我的同事讨论这个问题,我们决定真的要让 polyfill 保持原样,我们将在每个 for-in 循环中检查 hasOwnProperty 函数的结果。感谢您的帮助!

标签: javascript arrays enumerable for-in-loop


【解决方案1】:

一般来说,您可以使用Object.defineProperty 将属性添加为不可枚举:

Object.defineProperty(Array.prototytpe, 'indexOf', {
  enumerable : false,
  value : function(){ /* my polyfill code */}
});

但是,正如您可能已经猜到的那样,IE8 不支持它,因此您只能使用@tkone 的解决方案,即使用hasOwnProperty 过滤for..in


另一个伪解决方案是创建一个将数组参数传递给的函数:

function indexOf(array, searchElement, fromIndex) {
  if (Array.prototype.indexOf) return array.indexOf(searchElement, fromIndex);
  /* my polyfill code with array instead of this*/
}

并简单地使用它而不是本机 indexOf:

[1,2,3].indexOf(2); // change to:
indexOf([1,2,3], 2);

您也可以为您的函数命名,以便在您不再使用 IE8 时记得将其更改回标准:

IhateIE8.indexOf = ...

【讨论】:

    【解决方案2】:

    是否可以使 polyfill “不可枚举”,以便我能够在 IE 8 中使用 Array.indexOf(),但它不会出现在 for..in 循环中?

    正式来说,是的(请参阅definePropertyenumerable),但专门针对 IE8 及更低版本,not really

    我认为这不是一个好主意(请参阅 cmets)。

    【讨论】:

      【解决方案3】:

      在枚举对象的成员时应该使用hasOwnProperty

      var a = [];
      a[0] = 123;
      a[1] = 456;
      for(var value in a){
          if(a.hasOwnProperty(value)){
              alert(value);
          }
      }
      

      但是你为什么不只是做一个简单的for 循环(或填充类似forEach 的东西)

      【讨论】:

      • 备案:jshint 选项被称为forin 以防止for..in 循环没有这个检查。
      • 见我上面的评论。我们不能为代码中的每个 for..in 循环都实现这一点。我要么必须删除 polyfill,要么使其无法编号。
      • 嗯,首先,你应该重构你的代码库。由于可枚举的问题,使用for...in 进行数组枚举是一个非常糟糕的主意。第二,你可以。它被称为使用正则表达式的搜索和替换。 :)
      • @PaulMa 也是,如果是这种情况,那么就不可能按照您的要求进行操作。 IE8 不支持可枚举标志的概念。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-09
      • 2011-03-22
      • 2016-11-26
      • 1970-01-01
      • 2020-02-21
      相关资源
      最近更新 更多