javascript:防止将添加的Array属性表示为元素(在Chrome中)

时间:2013-12-10 10:18:38

标签: javascript arrays google-chrome

我正在使用此代码片段使用getUnique函数扩展Array的功能:

Array.prototype.getUnique = function() {
   var u = {}, a = [];
   for (var i = 0, l = this.length; i < l; ++i) {
      if (u.hasOwnProperty(this[i])) {
         continue;
      }
      a.push(this[i]);
      u[this[i]] = 1;
   }
   return a;
};

稍微有点缺点是,如果我在控制台上,则getUnique属性与数组元素一起打印.log一个数组:

["126", "125", getUnique: function]

即使我知道getUnique不被视为数组元素,这也有点令人不安。这种情况发生在Chrome中。据我所知,不是在Firefox中。有没有办法阻止它?

1 个答案:

答案 0 :(得分:3)

使用Object.definePropertyenumerable

Object.defineProperty(Array.prototype, 'getUnique',
{ enumerable: false
, configurable: true
, writable: true
, value: function ()
   {  var u = {};
      var a = [];
      for (var i = 0, l = this.length; i < l; ++i)
      {  if (u.hasOwnProperty(this[i])) continue;
         a.push(this[i]);
         u[this[i]] = 1;
      }
      return a;
   }
});

默认情况下,属性是可枚举的(即使它不是实例的直接属性),这意味着它可以通过数组的任何for-in循环(或Object.keys)可见。 Chrome在数组上执行类似于for-in循环的操作,这就是为什么它按原样表示的原因。

请注意,此功能仅适用于支持ES5的(相对)现代浏览器,这意味着IE&lt; 9,一些较旧的Android浏览器和其他移动设备可能无法使用此代码。这是为什么有些人建议不要扩展原生构造函数的原型的原因之一,因为这个问题可能会破坏那些针对这些问题构建得不好的代码。相信这通常建议的人不是将功能放在原型上:

function getUnique(arr)
{  var u = {};
   var a = [];
   for (var i = 0, l = array.length; i < l; ++i)
   {  if (u.hasOwnProperty(arr[i])) continue;
      a.push(arr[i]);
      u[arr[i]] = 1;
   }
   return a;
}

我还想指出getUnique函数只会打印一个对象,因为它的实现在技术上是不正确的。虽然相似,对象不是字典,只能有字符串键,这意味着任何对象(无论内容)都会有一个字符串值'[object Object]',这意味着当你的函数遇到另一个对象(即使它有不同的值),它不会被添加到返回的数组中。虽然效率低下,但我能想到的唯一方法是每次迭代数组:

function getUnique(arg)
{  'use strict';
   var O = Object(arg);
   var len = O.length >>> 0;
   var A = [];
   var indexOf = function (arg, searchElement)
   {  for (var i = 0, l = arg.length; i < l; ++i) if (arg[i] === searchElement) return i;
      return -1;
   };
   for (var k = 0; k < len; ++k)
   {  var elementK = O[k];
      var kPresent = k in O;
      if (!kPresent || indexOf(A, elementK) !== -1) continue;
      A[A.length - 1] = elementK;
   }
   return array;
}