为 Array 对象添加一个去除重复项的方法 输入:
[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a', 'a', NaN]输出:
[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a']一开始写法:
Array.prototype.uniq = function () { var res=[]; var obj={}; var len=this.length; for(var i=0;i<len;i++){ if(!obj[this[i]]){ obj[this[i]]='ok'; res.push(this[i]); } } return res; }把数组值保存到对象中,如果属性值为空,就添加数组元素到属性名中,然后随便给个属性值占位,数组元素如果已经在属性名中,则不进行添加操作。似乎没问题,但是这样显然是错的,不符合题目输出的要求,如 {} {}也被排除了
参考网上的解法,一开始不解为什么这种解法是正确的,因为错误的理解了 {} != {}
Array.prototype.uniq = function () { var res=[]; var flag = true; this.forEach(function(item){ //让 NaN 只添加一次 if(item!==item){ if(flag&&res.indexOf(item)===-1){ res.push(item); flag=false; } } else if(res.indexOf(item)===-1){ res.push(item); } }) return res; } }数组下标不存在 怎么表示:res.indexOf(item)===-1
这里重点理解 NaN != NaN 和 {} 首先 NaN 本身确实不等于它自己,在循环中可以通过 item != item 体现,左右两边的 item 是同一个,所以上面的派出NaN 方法是正确的,而且不会错误的排除 {} 然后重点:左右的 item肯定是同一个 item ,当item 为 一个对象时,它本身肯定是会等于它本身啊 ,**一个对象肯定会等于它本身,**所以不会满足 item != item 条件 一个对象肯定会等于它自己啊,但是注意输入案例中的两个 {} 不相等,因为它们是两个不同的 对象,只不过这两个对象里面都是空的
同一个 {} :,a中存的是一个空对象的地址,然后赋值给 b , a和 b 存的是同一个地址,指向同一块空间 不同的 {} ,两个不同的空对象,在不同的空间,c中存的是一个地址,指向一个空对象,d 中存的是另一个地址,指向另一个空对象,两者指向不同的 空间