为 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
中存的是另一个地址,指向另一个空对象,两者指向不同的 空间