ES6中Object.assign方法使用詳解
1、前言
首先了解下Object.assign()是什么。我們先看看ES6官方文檔是怎么介紹的?
Object.assign() 方法用于將所有可枚舉屬性的值從一個(gè)或多個(gè)源對(duì)象復(fù)制到目標(biāo)對(duì)象。它將返回目標(biāo)對(duì)象。
注意:Object.assign() 方法至少需要兩個(gè)對(duì)象作為參數(shù),第一個(gè)參數(shù)是目標(biāo)對(duì)象,后面的參數(shù)都是源對(duì)象。
2、語法
語法:
Object.assign(target, ...sources)
參數(shù):target
—>目標(biāo)對(duì)象
source
—>源對(duì)象
返回值:target
,即目標(biāo)對(duì)象
3、基本用法
3.1 目標(biāo)對(duì)象和源對(duì)象無重名屬性
var target = { name: '張三', age: 18 } var source = { money: '10000' } var result = Object.assign(target, source) console.log(result) console.log(target);
運(yùn)行結(jié)果如下:
我們可以看到source上的state屬性合并到了target對(duì)象上。如果只是想將兩個(gè)或多個(gè)對(duì)象的屬性合并到一起,不改變?cè)袑?duì)象的屬性,可以用一個(gè)空的對(duì)象作為target對(duì)象。像下面這樣:
var target = { name: '張三', age: 18 } var source = { money: '10000' } var result = Object.assign({}, target, source) console.log(result);
運(yùn)行結(jié)果如下:
3.2 目標(biāo)對(duì)象和源對(duì)象有重名屬性
var target = { name: '張三', age: 18 } var source = { money: '10000', age: 28 } var result = Object.assign(target, source) console.log(target)
運(yùn)行結(jié)果如下:
可以看到如果有同名屬性的話,后面的屬性值會(huì)覆蓋前面的屬性值。
3.3 有多個(gè)源對(duì)象
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)
運(yùn)行結(jié)果如下:
可以看到有多個(gè)源對(duì)象情況也是和一個(gè)源對(duì)象一樣的。沒有同名的屬性會(huì)直接復(fù)制到目標(biāo)對(duì)象上,同名的屬性后面的屬性值會(huì)覆蓋前面的同名屬性值。
3.4 其他情況
3.4.1 只有一個(gè)參數(shù)時(shí),Object.assign會(huì)直接返回該參數(shù)
var obj = { a: 1 } console.log(Object.assign(obj)) console.log(Object.assign(obj) === obj);
運(yùn)行結(jié)果如下:
3.4.2 如果該參數(shù)不是對(duì)象,則會(huì)先轉(zhuǎn)成對(duì)象,然后返回
typeof Object.assign(2) // object
3.4.3 出現(xiàn)undefined和null情況
由于undefined和null無法轉(zhuǎn)成對(duì)象,所以如果將它們作為參數(shù),就會(huì)報(bào)錯(cuò)。
Object.assign(undefined) Object.assign(null)
運(yùn)行結(jié)果如下:
注意:如果非對(duì)象參數(shù)出現(xiàn)在源對(duì)象的位置(即非首參數(shù)),那么處理規(guī)則將有所不同。首先,這些參數(shù)都會(huì)被轉(zhuǎn)成對(duì)象,如果無法轉(zhuǎn)成對(duì)象便會(huì)跳過。這意味著,如果undefined和null不在首參數(shù)便不會(huì)報(bào)錯(cuò)。
let obj = { a: 1 } Object.assign(obj, undefined) === obj // true Object.assign(obj, null) === obj // true
3.4.4 其他類型的值
其他類型的值(即數(shù)值、字符串、布爾值)不在首參數(shù)也不會(huì)出錯(cuò)。但是,除了字符串會(huì)以數(shù)組形式賦值到目標(biāo)對(duì)象,其他值都不會(huì)產(chǎn)生效果。
var v1 = 'abc' var v2 = true var v3 = 10 var obj = Object.assign({}, v1, v2, v3) console.log(obj);
運(yùn)行結(jié)果如下:
上面的代碼中,v1, v2, v3分別是字符串、布爾值和數(shù)值,結(jié)果只有字符串合入目標(biāo)對(duì)象(以字符數(shù)組的形式),數(shù)值和布爾值都會(huì)被忽略。這是因?yàn)橹挥凶址陌b對(duì)象會(huì)產(chǎn)生枚舉屬性。
console.log(Object(true)) console.log(Object(10)) console.log(Object('abc'));
運(yùn)行結(jié)果如下:
上面的代碼中,布爾值、數(shù)值、字符串分別轉(zhuǎn)成對(duì)應(yīng)的包裝對(duì)象,可以看到它們的原始值都在包裝對(duì)象的內(nèi)部屬性[[PrimitiveValue]]上面,這個(gè)屬性是不會(huì)被Object.assign() 復(fù)制的。只有字符串的包裝會(huì)產(chǎn)生可枚舉的實(shí)義屬性,那些屬性則會(huì)被拷貝。
Object.assign 復(fù)制的屬性是有限制的,只復(fù)制源對(duì)象的自身屬性(不復(fù)制繼承屬性),也不復(fù)制不可枚舉的屬性(enumerable: false)。
let obj = Object.assign({ b: 'c' }, Object.defineProperty({}, 'invisible', { enumerable: false, value: 'hello world' }) ) console.log(obj);
運(yùn)行結(jié)果如下:
上面的代碼中,Object.assign要復(fù)制的對(duì)象只有一個(gè)不可枚舉對(duì)屬性invisible,這個(gè)屬性并沒有被復(fù)制進(jìn)去。
屬性名為Symbol值的屬性也會(huì)被Object.assign復(fù)制。
let obj = Object.assign({ b: 'c' }, { [Symbol('c')]: 'd' }) console.log(obj);
運(yùn)行結(jié)果如下:
4、高級(jí)用法
4.1 為對(duì)象添加屬性
class Point { constructor(x, y) { Object.assign(this, { x, y }) console.log(this) } } const p1 = new Point('12', '23') console.log(p1);
運(yùn)行結(jié)果如下:
上面的方法通過assign方法將x屬性和y屬性添加到了Point類的對(duì)象實(shí)例中。
4.2 為對(duì)象添加方法
Object.assign(SomeClass.prototype, { someMethod (argl, arg2) { ... }, anotherMethod () { ... }, }) 等同于下面的寫法 SomeClass.prototype.someMethod = function (argl, arg2) { ... } SomeClass.prototype.anotherMethod = function () { ... }
上面的代碼使用了對(duì)象屬性的簡(jiǎn)潔表示法,直接將兩個(gè)函數(shù)放在大括號(hào)中,再使用assign方法添加到SomeClass.prototype中。
4.3 克隆對(duì)象
function clone (origin) { return Object.assign({}, origin) }
上面的代碼將原始對(duì)象復(fù)制到一個(gè)空對(duì)象中,就得到了原始對(duì)象的克隆。
不過,采用這種方法只能克隆原始對(duì)象自身的值,不能克隆它繼承的值。如果想要保持繼承鏈,可以采用下面這段代碼。
function clone (origin) { let originProto = Object.getPrototypeOf(origin) return Object.assign(Object.create(originProto), origin) }
4.4 合并多個(gè)對(duì)象
- 將多個(gè)對(duì)象合并到某個(gè)對(duì)象
const merge = (target, ...sources) => Object.assign(target, ...sources);
- 如果希望合并后返回一個(gè)新對(duì)象,可以改寫上面的函數(shù),對(duì)一個(gè)空對(duì)象合并。
const merge = (...sources) => Object.assign({}, ...sources);
4.4 為屬性指定默認(rèn)值
const DEFAULTS = { logLevel: 0, outputForrnat: 'html' } function processContent (options) { options = Object.assign({}, DEFAULTS, options) console.log(options) }
上面的代碼中,DEFAULTS 對(duì)象是默認(rèn)值,options對(duì)象是用戶提供的參數(shù)。
Object.assign方法將DEFAULTS和options合并成一個(gè)新對(duì)象,如果兩者有同名屬性,則options的屬性值會(huì)覆蓋DEFAULTS 屬性值。
注意:由于存在深復(fù)制的問題,DEFAULTS對(duì)象和options對(duì)象的所有屬性
的值都只能是簡(jiǎn)單類型,而不能指向另一個(gè)對(duì)象,否則將導(dǎo)致DEFAULTS對(duì)象的該屬性不起作用。
const DEFAULTS = { url: { host: 'example.corn', port: 7070 } } processContent ( { url: {port : 8000} } ) //{ // url: {port: 8000) //}
上面的代碼原意是將url.port改成8000,而url.host保持不變。實(shí)際結(jié)果卻是options.url覆蓋了DEFAULTS.url,所以u(píng)rl.host就不復(fù)存在了。
5、注意事項(xiàng)
1、Object.assign 方法只會(huì)拷貝源對(duì)象自身的并且可枚舉的屬性到目標(biāo)對(duì)象,繼承屬性和不可枚舉屬性是不能拷貝的;
2、針對(duì)深拷貝,需要使用其他辦法,因?yàn)?Object.assign()拷貝的是屬性值。假如源對(duì)象的屬性值是一個(gè)對(duì)象的引用,那么它也只指向那個(gè)引用;
3、目標(biāo)對(duì)象自身也會(huì)改變;
4、異常會(huì)打斷后續(xù)拷貝任務(wù);
5、Object.assign可以用來處理數(shù)組,但是會(huì)把數(shù)組視為對(duì)象來處理。
let obj = Object.assign([1, 2, 3], [4, 5]) console.log(obj); // [4, 5, 3]
上面的代碼中, Object.assign把數(shù)組視為屬性名為0、1、2的對(duì)象,因此目標(biāo)數(shù)組的0號(hào)屬性覆蓋了0號(hào)屬性1。
6、兼容性
目前IE瀏覽器不兼容Object.assign(),如果需要兼容IE的話最好不要直接使用這個(gè)方法。
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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IE和Firefox下javascript的兼容寫法小結(jié)
學(xué)習(xí)js的朋友必須要知道或了解的知識(shí)2008-12-12JavaScript模擬實(shí)現(xiàn)繼承的方法
這篇文章主要介紹了JavaScript模擬實(shí)現(xiàn)繼承的方法,實(shí)例分析了javascript類的操作與模擬實(shí)現(xiàn)繼承的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03