可用apply配合Set去重但不推荐,因Set构造函数只接受单个可迭代参数,apply直接传数组会报错;现代应优先使用[...new Set(arr)]或Array.from(new Set(arr))。

可以用 Function.prototype.apply 把数组“展开”传给 Set 构造函数,从而实现去重,但要注意:ES6 之后更推荐用扩展运算符(...),因为 apply 在处理超大数组时可能触发栈溢出,且写法略显迂回。
为什么能用 apply 配合 Set 去重
Set 构造函数接收一个**可迭代对象**(如数组)作为参数,自动去除重复项;而 apply 的作用是把数组的每一项作为独立参数传入函数。所以:new Set().constructor === Set,而 Set 是函数,因此可以被 apply 调用:
-
Set.apply(null, [1,2,2,3])等价于new Set(1, 2, 2, 3)—— 但这会报错,因为Set构造函数不接受多个独立参数,只接受一个可迭代参数 - ✅ 正确方式是:
new (Function.prototype.bind.apply(Set, [null, [1,2,2,3]])),但太绕 - ⚠️ 实际上,直接写
new Set([1,2,2,3])就够了,根本不需要apply
真正可行的 apply + Set 写法(仅作技术演示)
如果坚持用 apply,必须让 Set 接收一个数组作为**单个参数**,那就得借助 bind 或包装函数:
// 方式一:用 bind + apply 模拟 new Set(arr)
const arr = [1, 2, 2, 3];
const unique = new (Function.prototype.bind.apply(Set, [null, [arr]]))();
// 方式二:更清晰的等价写法(不推荐,仅说明原理)
const UniqueSet = Set.bind(null, arr);
const unique2 = new UniqueSet(); // → Set {1, 2, 3}
但以上都属于“绕路实现”,无实际优势,还降低可读性。
现代推荐做法:用扩展运算符替代 apply
去重最自然、安全、易读的方式是:
-
[...new Set(arr)]—— 数组去重并转回数组 -
Array.from(new Set(arr))—— 功能相同,兼容性稍好(支持类数组) - 如果原始数据是类数组(如
arguments或NodeList),可直接传给Set:new Set(arrayLike),无需apply
apply 的典型适用场景(对比说明)
apply 真正有用的地方是调用**已有函数**并动态传参,例如:
-
Math.max.apply(null, [1,5,3])→5(因为Math.max不接受数组) -
console.log.apply(console, ['a', 'b'])→ 输出a b - 而
Set本身设计为接收可迭代对象,不是为多参数设计的,所以硬套apply属于误用
不复杂但容易忽略:Set 去重靠的是值的严格相等(===),对对象引用无效;若需深去重,得另写逻辑,和 apply 无关。











