ES6 Object.assign() 方法详解:语法、用法与注意事项
本文详细解析 ES6 中 Object.assign() 方法的语法、基本用法及高级应用场景。涵盖属性合并、对象克隆、方法添加及默认值设置,并深入探讨其浅拷贝特性、不可枚举属性处理、异常中断机制及数组处理等注意事项,帮助开发者正确使用该 API。
前言
首先明确 Object.assign() 的功能定义。参考 ES6 官方文档的说明:
Object.assign() 方法的作用是将一个或多个源对象中所有可枚举属性的值复制到目标对象,并返回该目标对象。
需要注意的是,调用此方法时至少需要传入两个参数:第一个参数指定为目标对象,后续所有参数均为源对象。
语法
具体语法格式如下:
Object.assign(target, ...sources)
参数说明:target 代表目标对象。
source 代表源对象。
返回值:target,即被修改后的目标对象。
基本用法
3.1 目标对象与源对象无重名属性
var target = { name: '张三', age: 18 }
var source = { money: '10000' }
var result = Object.assign(target, source)
console.log(result)
console.log(target);
执行结果如下:

从结果可见,source 对象中的 state 属性已成功合并至 target 对象。若仅希望合并多个对象的属性而不修改原有对象,可传入一个空对象作为目标对象,示例如下:
var target = { name: '张三', age: 18 }
var source = { money: '10000' }
var result = Object.assign({}, target, source)
console.log(result);
执行结果如下:

3.2 目标对象与源对象存在重名属性
var target = { name: '张三', age: 18 }
var source = { money: '10000', age: 28 }
var result = Object.assign(target, source)
console.log(target)
执行结果如下:

当存在同名属性时,后续源对象中的属性值会覆盖目标对象或前面源对象中的同名属性值。
3.3 存在多个源对象的情况
var target = { name: '张三', age: 18 }
var source1 = { money: '10000', age: 28 }
var source2 = { mood: 'happy', age: 25 }
var result = Object.assign(target, source1, source2)
console.log(target)
执行结果如下:

多源对象的处理逻辑与单源对象一致:无重名属性直接复制到目标对象,重名属性则由后面的源对象值覆盖前面的值。
3.4 其他特殊情况
3.4.1 仅传入一个参数时
var obj = { a: 1 }
console.log(Object.assign(obj))
console.log(Object.assign(obj) === obj);
执行结果如下:

3.4.2 若参数非对象类型
typeof Object.assign(2) // object
3.4.3 处理 undefined 和 null 的情况
由于 undefined 和 null 无法转换为对象,若将它们作为第一个参数(目标对象)传入,程序将抛出错误。
Object.assign(undefined)
Object.assign(null)
执行结果如下:

需注意,若非对象参数出现在源对象位置(即非首参数),处理规则有所不同:这些参数会尝试转换为对象,若无法转换则被跳过。因此,undefined 和 null 若不在首参数位置,不会报错。
let obj = {
a: 1
}
Object.assign(obj, undefined) === obj // true
Object.assign(obj, null) === obj // true
3.4.4 其他数据类型
对于非首参数的其他数据类型(如数值、字符串、布尔值),处理结果各异:仅字符串会以数组形式赋值到目标对象,其他类型则不产生效果。
var v1 = 'abc'
var v2 = true
var v3 = 10
var obj = Object.assign({}, v1, v2, v3)
console.log(obj);
执行结果如下:

上述代码中,v1、v2、v3 分别为字符串、布尔值和数值。结果仅字符串合入目标对象(以字符数组形式),数值和布尔值被忽略。这是因为仅字符串的包装对象会产生可枚举属性。
console.log(Object(true))
console.log(Object(10))
console.log(Object('abc'));
执行结果如下:

上述代码中,布尔值、数值、字符串分别转换为对应的包装对象。可见其原始值存储于包装对象的内部属性 [[PrimitiveValue]] 中,该属性不会被 Object.assign() 复制。仅字符串包装会产生可枚举的实义属性,这些属性会被拷贝。Object.assign 的复制范围受限:仅复制源对象自身的可枚举属性,不复制继承属性及不可枚举属性(enumerable: false)。
let obj = Object.assign({ b: 'c' },
Object.defineProperty({}, 'invisible', {
enumerable: false,
value: 'hello world'
})
)
console.log(obj);
执行结果如下:

上述代码中,Object.assign 要复制的对象仅包含一个不可枚举属性 invisible,该属性未被复制。此外,属性名为 Symbol 值的属性也会被 Object.assign 复制。
let obj = Object.assign({ b: 'c' }, { [Symbol('c')]: 'd' })
console.log(obj);
执行结果如下:

高级用法
4.1 为对象添加属性
class Point {
constructor(x, y) {
Object.assign(this, { x, y })
console.log(this)
}
}
const p1 = new Point('12', '23')
console.log(p1);
执行结果如下:

上述方法通过 assign 将 x 和 y 属性添加至 Point 类的对象实例中。
4.2 为对象添加方法
Object.assign(SomeClass.prototype, {
someMethod (argl, arg2) {
...
},
anotherMethod () {
...
},
})
等同于下面的写法
SomeClass.prototype.someMethod = function (argl, arg2) {
...
}
SomeClass.prototype.anotherMethod = function () {
...
}
上述代码利用对象属性的简洁表示法,将两个函数置于大括号内,再通过 assign 方法添加至 SomeClass.prototype 中。
4.3 克隆对象
function clone (origin) {
return Object.assign({}, origin)
}
上述代码将原始对象复制至空对象,从而获得原始对象的克隆。但此方法仅克隆原始对象自身的值,不克隆继承值。若需保持继承链,可采用以下代码:
function clone (origin) {
let originProto = Object.getPrototypeOf(origin)
return Object.assign(Object.create(originProto), origin)
}
4.4 合并多个对象
- 将多个对象合并至某对象
const merge = (target, ...sources) => Object.assign(target, ...sources);
- 若希望合并后返回新对象,可改写上述函数,对空对象进行合并。
const merge = (...sources) => Object.assign({}, ...sources);
4.4 为属性指定默认值
const DEFAULTS = {
logLevel: 0,
outputForrnat: 'html'
}
function processContent (options) {
options = Object.assign({}, DEFAULTS, options)
console.log(options)
}
上述代码中,DEFAULTS 对象定义默认值,options 对象为用户提供的参数。Object.assign 将 DEFAULTS 和 options 合并为新对象,若两者存在同名属性,则 options 的属性值覆盖 DEFAULTS 的属性值。
注意:由于存在深复制问题,DEFAULTS 对象和 options 对象的所有属性值只能是简单类型,若指向另一对象,将导致 DEFAULTS 对象的该属性失效。
const DEFAULTS = {
url: {
host: 'example.corn',
port: 7070
}
}
processContent ( { url: {port : 8000} } )
//{
// url: {port: 8000)
//}
上述代码原意是将 url.port 修改为 8000,同时保持 url.host 不变。但实际结果是 options.url 覆盖了 DEFAULTS.url,导致 url.host 丢失。
注意事项
1、Object.assign 仅拷贝源对象自身的可枚举属性至目标对象,继承属性和不可枚举属性无法被拷贝;
2、针对深拷贝需采用其他方法,因为 Object.assign() 拷贝的是属性值。若源对象的属性值为对象引用,则目标对象仅指向该引用;
3、目标对象自身会被修改;
4、若发生异常,后续拷贝任务将中断;
5、Object.assign 可用于处理数组,但会将数组视为对象处理。
let obj = Object.assign([1, 2, 3], [4, 5])
console.log(obj); // [4, 5, 3]
上述代码中,Object.assign 将数组视为属性名为 0、1、2 的对象,因此目标数组的 0 号属性覆盖了 0 号属性 1。
兼容性
目前 IE 浏览器不兼容 Object.assign(),若需兼容 IE,建议避免直接使用此方法。
与 $.extend() 的比较
var target = { name: '张三', age: 18 }
var source1 = { state: 'single', age: 22 }
var source2 = { mood: 'happy', age: 25 }
var result = Object.assign(target, source1, source2)
console.log(target, 'assign')
var targetObj = { name: '张三', age: 18 }
var sourceObj1 = { state: 'single', age: 22 }
var sourceObj2 = { mood: 'happy', age: 25 }
var result = $.extend(targetObj, sourceObj1, sourceObj2)
console.log(targetObj, 'extend')
可见两者所得结果一致。
总结
至此,关于 ES6 中 Object.assign 方法使用的介绍结束。更多相关 ES6 Object.assign 方法内容,请搜索本站历史文章或继续浏览后续相关文章。希望大家以后多多支持本站!
JS语法错误会阻止加载吗?区分SyntaxError与资源加载失败
2026-11-05 16:08:46
JavaScript常见SyntaxError语法错误排查与修复方法
2026-11-05 13:58:44
JS中slice、substring和substr截取字符串的区别
2026-11-05 13:43:47
JS 转 TS 手动迁移最佳实践:从配置 tsconfig 到消除 any 类型
2026-11-05 11:53:32
为什么JS数组push后得到的是数字而不是数组?
2026-11-05 09:59:18
