关于数组去重问题引发的一系列思考

时间:2021-09-23 23:31:07

其实取这个名字可能不太符合实际,毕竟没有“一系列”╮(╯_╰)╭
问题引发是牛客网上js的数组去重编程题,
先放一个正确版本的代码:

Array.prototype.uniq = function(){
var arr = this;
var newArr = [];
var flag = 0;
for(var i = 0;i < arr.length; i++){
if(newArr.indexOf(arr[i])== -1){ //可能是NaN,{},第一次出现的值
if(arr[i] != arr[i]){
if(arr[i].toString() == "NaN" && flag == 0){
newArr.push(arr[i]);
flag =1;
}
}else{
newArr.push(arr[i]);
}
}
}
return newArr;
}

嘛,本来事情到这里ac通过了就没有之后的下文了,不过因为某些原因,我去尝试另外一种方法:

Array.prototype.uniq = function(){
var arr = this;
var newArr = [];

var obj = {};
for(var i = 0;i < arr.length; i++){

if(arr[i] && typeof arr[i] === 'object'){
newArr.push(arr[i]);

continue;
}
if(obj.hasOwnProperty(arr[i])){
continue;
}
obj[arr[i]] = arr[i];
newArr.push(arr[i]);
}
return newArr;
}

遗憾的是,这段代码没有ac通过,当时怎么想都没想出来,网上也求助了很多人,明白了一些漏考虑的例子:

  1. 比如说引用相同的对象
  2. (有点忘了)…

但是把这些加上去还是只通过50%。。。。

然后,重点来了!

[1,'1',null,undefined,NaN,false,true,{},[],function(){},'NaN','false'].uniq();
的结果正确的应该是
[1,'1',null,undefined,NaN,false,true,{},[],function(){},'NaN','false'],
而我的是
[1,'1',null,undefined,NaN,false,true,{},[],function(){}]

==================================
这个的原因应该是
对象设置属性的时候会将属性名转成字符串
那么是怎么转的呢?刚开始并没有直接去找这个的相关资料,而是自己测试了一些案例,发现,基本所有类型的key放进去obj里面都会变成string:

var arr = [1,'1',null,undefined,NaN,false,true,{},[],function(){}];
arr.forEach(function(item,index){obj[item] = index});

//结果Object {1: 1, null: 2, undefined: 3, NaN: 4, false: 5, true: 6…}

由此,联想是不是它自动使用 toString()转化,又测试:

arr.forEach(function(item,index){console.log(item.toString())})

//结果 报错VM554:
1 Uncaught TypeError: Cannot read property 'toString' of null(…)

结果报错了,undefined,null,没有toString()方法,又想是不是用了valueOf (),仍旧报错。。。。o(╯□╰)o

=================
后来找了度娘查看toString()的情况。。。揭秘:

其实这里应该是用了强制类型转化,String()

w3c上面有解释:
关于数组去重问题引发的一系列思考

关于强制类型转化,w3c上有简要的解释:
http://www.w3school.com.cn/js/pro_js_typeconversion.asp

Well , that’s all……