iterator本身不直接实现浅拷贝,但展开运算符(...)通过调用[symbol.iterator]方法消费可迭代对象(如数组、set、map),在原生类型上产生浅拷贝效果;普通对象不可迭代,{...obj}不依赖iterator而是枚举属性。

JavaScript 中,Iterator 本身不直接实现浅拷贝,但可以通过展开运算符(...)消费可迭代对象(如数组、Set、Map 的键值等),从而在特定场景下达成类似浅拷贝的效果。关键在于:展开运算符会调用对象的 [Symbol.iterator] 方法,将可迭代结构“解构”为新实例,而这个过程对数组或 Set 等原生类型天然产生浅拷贝结果。
数组用展开运算符实现浅拷贝
数组是可迭代对象,其默认 Iterator 逐项返回元素。使用展开运算符创建新数组时,会复制引用(而非深拷贝),因此属于浅拷贝。
例如:
const original = [1, 2, { name: 'Alice' }];
const copy = [...original];
copy[0] = 99; // 修改基础类型 —— 不影响 original
copy[2].name = 'Bob'; // 修改对象属性 —— original[2].name 也变成 'Bob'
console.log(original); // [1, 2, { name: 'Bob' }]
Set 和 Map 的浅拷贝也依赖 Iterator
Set 和 Map 的默认 Iterator 分别遍历值和键值对。展开后生成新实例,同样只复制引用。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
Set 浅拷贝:
const newSet = new Set([...oldSet]);—— 新 Set 包含相同元素引用 -
Map 浅拷贝:
const newMap = new Map([...oldMap]);—— 键值对被重新插入,但对象/函数等引用仍共享
注意:不是所有对象都能这样拷贝
普通对象(plain object)默认不可迭代,不能直接用 {...obj} 触发 Iterator;此时展开运算符实际使用的是对象自身的可枚举属性遍历逻辑(类似 Object.assign({}, obj)),并非调用 [Symbol.iterator]。所以严格来说,{...obj} 的行为与 Iterator 无关,只是语法糖。
若想让自定义对象支持展开浅拷贝,需手动实现 [Symbol.iterator] 方法,并确保它返回合适的迭代器(如逐个 yield 属性值),但要注意这不会自动处理键名,也不等价于对象拷贝语义。
替代方案:明确意图,避免混淆
如果目标是浅拷贝,优先使用语义清晰的方式:
- 数组 →
[...arr]或arr.slice()或Array.from(arr) - Set →
new Set(set)(内部调用 Iterator) - Map →
new Map(map)(同理) - 普通对象 →
{...obj}或Object.assign({}, obj)(非 Iterator 机制)
理解背后的机制有助于选对方法,而不是把展开运算符当作“通用浅拷贝黑箱”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










