ES6中Object.assign方法使用詳解
1、前言
首先了解下Object.assign()是什么。我們先看看ES6官方文檔是怎么介紹的?
Object.assign() 方法用于將所有可枚舉屬性的值從一個或多個源對象復制到目標對象。它將返回目標對象。
注意:Object.assign() 方法至少需要兩個對象作為參數(shù),第一個參數(shù)是目標對象,后面的參數(shù)都是源對象。
2、語法
語法:
Object.assign(target, ...sources)
參數(shù):target—>目標對象
source—>源對象
返回值:target,即目標對象
3、基本用法
3.1 目標對象和源對象無重名屬性
var target = { name: '張三', age: 18 }
var source = { money: '10000' }
var result = Object.assign(target, source)
console.log(result)
console.log(target);
運行結(jié)果如下:

我們可以看到source上的state屬性合并到了target對象上。如果只是想將兩個或多個對象的屬性合并到一起,不改變原有對象的屬性,可以用一個空的對象作為target對象。像下面這樣:
var target = { name: '張三', age: 18 }
var source = { money: '10000' }
var result = Object.assign({}, target, source)
console.log(result);
運行結(jié)果如下:

3.2 目標對象和源對象有重名屬性
var target = { name: '張三', age: 18 }
var source = { money: '10000', age: 28 }
var result = Object.assign(target, source)
console.log(target)
運行結(jié)果如下:

可以看到如果有同名屬性的話,后面的屬性值會覆蓋前面的屬性值。
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)
運行結(jié)果如下:

可以看到有多個源對象情況也是和一個源對象一樣的。沒有同名的屬性會直接復制到目標對象上,同名的屬性后面的屬性值會覆蓋前面的同名屬性值。
3.4 其他情況
3.4.1 只有一個參數(shù)時,Object.assign會直接返回該參數(shù)
var obj = { a: 1 }
console.log(Object.assign(obj))
console.log(Object.assign(obj) === obj);
運行結(jié)果如下:

3.4.2 如果該參數(shù)不是對象,則會先轉(zhuǎn)成對象,然后返回
typeof Object.assign(2) // object
3.4.3 出現(xiàn)undefined和null情況
由于undefined和null無法轉(zhuǎn)成對象,所以如果將它們作為參數(shù),就會報錯。
Object.assign(undefined) Object.assign(null)
運行結(jié)果如下:

注意:如果非對象參數(shù)出現(xiàn)在源對象的位置(即非首參數(shù)),那么處理規(guī)則將有所不同。首先,這些參數(shù)都會被轉(zhuǎn)成對象,如果無法轉(zhuǎn)成對象便會跳過。這意味著,如果undefined和null不在首參數(shù)便不會報錯。
let obj = {
a: 1
}
Object.assign(obj, undefined) === obj // true
Object.assign(obj, null) === obj // true
3.4.4 其他類型的值
其他類型的值(即數(shù)值、字符串、布爾值)不在首參數(shù)也不會出錯。但是,除了字符串會以數(shù)組形式賦值到目標對象,其他值都不會產(chǎn)生效果。
var v1 = 'abc'
var v2 = true
var v3 = 10
var obj = Object.assign({}, v1, v2, v3)
console.log(obj);
運行結(jié)果如下:

上面的代碼中,v1, v2, v3分別是字符串、布爾值和數(shù)值,結(jié)果只有字符串合入目標對象(以字符數(shù)組的形式),數(shù)值和布爾值都會被忽略。這是因為只有字符串的包裝對象會產(chǎn)生枚舉屬性。
console.log(Object(true))
console.log(Object(10))
console.log(Object('abc'));
運行結(jié)果如下:

上面的代碼中,布爾值、數(shù)值、字符串分別轉(zhuǎn)成對應的包裝對象,可以看到它們的原始值都在包裝對象的內(nèi)部屬性[[PrimitiveValue]]上面,這個屬性是不會被Object.assign() 復制的。只有字符串的包裝會產(chǎn)生可枚舉的實義屬性,那些屬性則會被拷貝。
Object.assign 復制的屬性是有限制的,只復制源對象的自身屬性(不復制繼承屬性),也不復制不可枚舉的屬性(enumerable: false)。
let obj = Object.assign({ b: 'c' },
Object.defineProperty({}, 'invisible', {
enumerable: false,
value: 'hello world'
})
)
console.log(obj);
運行結(jié)果如下:

上面的代碼中,Object.assign要復制的對象只有一個不可枚舉對屬性invisible,這個屬性并沒有被復制進去。
屬性名為Symbol值的屬性也會被Object.assign復制。
let obj = Object.assign({ b: 'c' }, { [Symbol('c')]: 'd' })
console.log(obj);
運行結(jié)果如下:

4、高級用法
4.1 為對象添加屬性
class Point {
constructor(x, y) {
Object.assign(this, { x, y })
console.log(this)
}
}
const p1 = new Point('12', '23')
console.log(p1);
運行結(jié)果如下:

上面的方法通過assign方法將x屬性和y屬性添加到了Point類的對象實例中。
4.2 為對象添加方法
Object.assign(SomeClass.prototype, {
someMethod (argl, arg2) {
...
},
anotherMethod () {
...
},
})
等同于下面的寫法
SomeClass.prototype.someMethod = function (argl, arg2) {
...
}
SomeClass.prototype.anotherMethod = function () {
...
}
上面的代碼使用了對象屬性的簡潔表示法,直接將兩個函數(shù)放在大括號中,再使用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);
- 如果希望合并后返回一個新對象,可以改寫上面的函數(shù),對一個空對象合并。
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對象是用戶提供的參數(shù)。
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保持不變。實際結(jié)果卻是options.url覆蓋了DEFAULTS.url,所以url.host就不復存在了。
5、注意事項
1、Object.assign 方法只會拷貝源對象自身的并且可枚舉的屬性到目標對象,繼承屬性和不可枚舉屬性是不能拷貝的;
2、針對深拷貝,需要使用其他辦法,因為 Object.assign()拷貝的是屬性值。假如源對象的屬性值是一個對象的引用,那么它也只指向那個引用;
3、目標對象自身也會改變;
4、異常會打斷后續(xù)拷貝任務;
5、Object.assign可以用來處理數(shù)組,但是會把數(shù)組視為對象來處理。
let obj = Object.assign([1, 2, 3], [4, 5]) console.log(obj); // [4, 5, 3]
上面的代碼中, Object.assign把數(shù)組視為屬性名為0、1、2的對象,因此目標數(shù)組的0號屬性覆蓋了0號屬性1。
6、兼容性
目前IE瀏覽器不兼容Object.assign(),如果需要兼容IE的話最好不要直接使用這個方法。
7、與$.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')
可以看到兩者得到的結(jié)果是一樣的。
總結(jié)
到此這篇關(guān)于ES6中Object.assign方法使用的文章就介紹到這了,更多相關(guān)ES6 Object.assign方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IE和Firefox下javascript的兼容寫法小結(jié)
學習js的朋友必須要知道或了解的知識2008-12-12

