1. 要想搞明白数组去重的各种方案,第一步要做的事就是什么是重复的元素,先来看一段代码结果
    2. /**
    3. * 谈到数组去重,几乎是面试必备的一道开胃菜
    4. * 要想数组去重,第一件事就是有一个数组
    5. */
    6. // 首先第一步
    7. console.log(1 === 1); // true
    8. console.log("1" === "1"); // true
    9. console.log("true" === "true"); // true
    10. console.log(false === false); // true
    11. console.log(undefined === undefined); // true
    12. console.log(null === null); // true
    13. console.log(NaN === NaN); // false
    14. console.log({} === {}); // false
    15. console.log([] === []); // false
    16. 接着第二步:准备含有重复元素的目标数组
    17. let targetArr = ["1", "1", 1, 1, true, true, undefined, undefined, null, null];
    18. console.log(targetArr);
    19. 第三步:写去重方法,这时候才是正是写方法的时候
    20. /**
    21. * desc 第一种方案 双层for循环
    22. */
    23. function unique1(arr) {
    24. let result = []; // 结果数组
    25. for (let i = 0, len = arr.length; i < len; i++) {
    26. for (var j = 0, resLen = result.length; j < resLen; j++) {
    27. if (arr[i] === result[j]) {
    28. break;
    29. }
    30. }
    31. if (j === result.length) {
    32. result.push(arr[i]);
    33. }
    34. }
    35. return result;
    36. }
    37. /**
    38. * desc 第二种方案 indexOf
    39. */
    40. const unique2 = (arr) => {
    41. let result = [];
    42. for (let i = 0, len = arr.length; i < len; i++) {
    43. if (result.indexOf(arr[i]) === -1) {
    44. // 在结果数组中没有找到元素
    45. result.push(arr[i]);
    46. }
    47. }
    48. return result;
    49. };
    50. /**
    51. * desc 第三种方案 先给数组排序结合 sort函数
    52. */
    53. const unique3 = (target) => {
    54. target.sort();
    55. let result = [target[0]]; // 取出第一个元素
    56. for (let i = 1; i < target.length; i++) {
    57. target[i] !== target[i - 1] && result.push(target[i]); // 当前项和它的前一项不同的时候,才添加进结果数组
    58. }
    59. return result;
    60. };
    61. /**
    62. * desc 第四种方案 使用filter 函数结合 indexof
    63. */
    64. const unique4 = (target) => {
    65. return target.filter((item, index) => {
    66. return target.indexOf(item) === index; // 数组的下标与检索的下标一致
    67. });
    68. };
    69. /**
    70. * desc 第五种方案 使用对象的键值对 结合obj.hasOwnProperty()
    71. */
    72. const unique5 = (target) => {
    73. let obj = {}; // 初始化一个空的对象
    74. let result = new Array();
    75. result = target.filter((item, index) =>
    76. // typeof item + item 主要是考虑到 对象的key 数值1 会被搞成 '1'
    77. obj.hasOwnProperty(typeof item + item)
    78. ? false
    79. : (obj[typeof item + item] = true)
    80. );
    81. return result;
    82. };
    83. /**
    84. * desc 第六种方案 使用ES6的新语法Set
    85. *
    86. */
    87. const unique6 = (target) => {
    88. // Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。
    89. let x = new Set(target); // Set { '1', 1, true, null }
    90. return [...x]; // 转为数组
    91. };
    92. /**
    93. * desc 第七种方案 使用ES6的Array.from
    94. *
    95. */
    96. const unique7 = (target) => {
    97. // Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。
    98. let x = new Set(target); // Set { '1', 1, true, null }
    99. return Array.from(x); // 转为数组
    100. };
    101. /**
    102. * desc 第八种方案 使用哈希表
    103. *
    104. */
    105. const unique8 = (target) => {
    106. let result = []; // 结果数组
    107. let hash = {};
    108. for (let ele of target) {
    109. if (!hash[ele]) {
    110. // hash 中没有数组中的元素
    111. result.push(ele); // 把元素放进去
    112. hash[ele] = true; // hash中已经存在了标记为true 下次循环就不会接着往结果数组中放相同的元素了
    113. }
    114. }
    115. return result;
    116. };
    117. /**
    118. * desc 第九种方案 使用Map 类型
    119. * 缺点 hash中存在相同的 key 就不往下找了, 但 '1' 和 1 是不同的元素
    120. * 请同学自行测试吧哈哈~
    121. */
    122. const unique9 = (target) => {
    123. let map = new Map(); // 初始化 map
    124. let result = new Array(); // 初始化 数组
    125. for (let i = 0; i < target.length; i++) {
    126. if (map.has(target[i])) {
    127. map.set(target[i], true);
    128. } else {
    129. map.set(target[i], false);
    130. result.push(target[i]);
    131. }
    132. }
    133. return result;
    134. };
    135. /**
    136. * desc 第十种方案 双层for循环变体
    137. *
    138. *
    139. */
    140. const unique10 = (target) => {
    141. // let result = [];
    142. for (let i = 0; i < target.length; i++) {
    143. for (let j = i + 1; j < target.length; j++) {
    144. if (target[i] === target[j]) {
    145. // 如果两项元素相同的话,则从目标元素中删除一个
    146. target.splice(j, 1);
    147. // splice 会改变原数组,所以相关的长度都要减去一
    148. i--;
    149. j--;
    150. }
    151. }
    152. }
    153. return target;
    154. };
    155. /**
    156. * desc 第十一种方案 数据的遍历结合includes
    157. *
    158. *
    159. */
    160. const unique11 = (target) => {
    161. let result = [];
    162. for (let ele of target) {
    163. // 其中 ele 是每一目标元素中每一元素
    164. !result.includes(ele) && result.push(ele); // 如果结果数组中没有ele就添加进去
    165. }
    166. return result;
    167. };
    168. /**
    169. * desc 第十二种方案 数据reduce
    170. *
    171. *
    172. */
    173. const unique12 = (target) => {
    174. return target.reduce((previousValue, currentValue, currentIndex) => {
    175. return previousValue.includes(currentValue)
    176. ? previousValue
    177. : [...previousValue, currentValue];
    178. }, []);
    179. };
    180. console.log(unique1(targetArr)); // ["1", 1, true, undefined, null]
    181. console.log(unique2(targetArr)); // ["1", 1, true, undefined, null]
    182. console.log(unique3(targetArr)); // ["1", 1, null, true, undefined]
    183. console.log(unique4(targetArr)); // ["1", 1, null, true, undefined]
    184. console.log(unique5(targetArr)); // ["1", 1, null, true, undefined]