使用Object.assign设置默认值
Object.assign接受任意数量的对象作为参数,将后续对象的值赋给第一个对象,如果任何对象包含相同的键,那么列表中右边的对象将会覆盖左边的对象
let objA={ name:"objA",age:10,address:"wuhan"}let objB={ name:"objB",age:12}let objC={ name:"objC",address:'shanghai'}Object.assign(objA,objB,objC)console.log(objA); // { name: 'objC', age: 12, address: 'shanghai' }复制代码
使用Object.assign扩展对象
案例:创造宇宙飞船游戏,拥有初级宇宙飞船形态和进化后的形态
// 构建基本类型的宇宙飞船function createBaseSpaceShip() { return { fly: function () { //飞行的方法 }, shoot: function () { //发射方法 }, destory: function () { // 用于飞船销毁时的函数 } }}//创建其他类型的宇宙飞船。拥有炸弹方法function createBomberSpaceShip() { let spaceship = createBaseSpaceShip(); Object.assign(spaceship, { bomb: function () { //飞船扔炸弹 } }) return spaceship;}let bomber=createBaseSpaceShip();bomber.fly();bomber.shoot();bomber.bomb() //调用的炸弹方法复制代码
使用上面的模板我们可以创建很多类型的宇宙飞船,,如果我们打算重用这个,那么我们可以创建辅助函数,来增强宇宙飞船
function createBaseSpaceShip() { return { fly: function () { //飞行的方法 }, shoot: function () { //发射方法 }, destory: function () { // 用于飞船销毁时的函数 } }}//辅助函数function enhancedSpaceShip(enhancements) { let spaceship = createBaseSpaceShip(); Object.assign(spcaeship, enhancements); return spaceship}function createBomberSpaceShip() { return enhancedSpaceShip({ bomb: function () { //飞船扔炸弹 } })}function createStealthSpaceShip() { return enhancedSpaceShip({ stealth: function () { //让飞船隐身 } })}let bomber = createBomberSpaceShip();bomber.shoot();bomber.bomb(); //投炸弹let stealthship = createStealthSpaceShip();stealthship.shoot();stealthship.stealth() //隐身复制代码
继续扩展飞船,使其拥有wrap函数
function createWarpSpaceShip() { return enhancedSpaceShip({ warp: function () { //让飞船速度提高 } })}复制代码
使用Object.assign时防止对象改变
大多数情况我们不喜欢改变现有对象,而只是希望返回一个具有所需改变的副本,原因是为了防止当前引用对象的一些东西由于引用的是源对象的,所以会发生改变,失去对某个对象的控制,
如:上面的宇宙飞船,如果没有创建基本宇宙飞船对象副本的函数,怎么处理?如果只有一个基本宇宙飞船对象,又怎么处理? 这些情况下,每次调用Object.assign来得到扩展是,都得增强基本宇宙飞船,而我们只是需要一个副本而已,使得基本宇宙飞船不发生变化
你可能会想到使用const,但是const只能防止使用新对象重新变量,并不能防止改变现有对象,可以看看我之前写的const那一篇中提到的
Object.assign的会将后续位置的值赋值给第一个对象,所以它改变了参数列表中的第一个对象,使其余对象保持不变,所以常见的做法就是使第一个对象为空字面量对象
let obj = Object.assign({}, { nameA: 'objA' }, { nameB: 'objB', age: 18 });console.log(obj); //{ nameA: 'objA', nameB: 'objB', age: 18 }复制代码
重写案例
//使用基本对象和增强函数制作一个增强型对象const baseSpaceShip={ fly: function () { //飞行的方法 }, shoot: function () { //发射方法 }, destory: function () { // 用于飞船销毁时的函数 }}//辅助函数function enhancedSpaceShip(enhancements) { // let spaceship = createBaseSpaceShip(); // Object.assign(spcaeship, enhancements); // return spaceship //将空字面量对象作为第一个参数,生成副本 return Object.assign({},baseSpaceShip,enhancements)}function createBomberSpaceShip() { return enhancedSpaceShip({ bomb: function () { //飞船扔炸弹 } })}function createStealthSpaceShip() { return enhancedSpaceShip({ stealth: function () { //让飞船隐身 } })}//扩展: 编写一个拥有炸弹轰炸和隐形功能的宇宙飞船function createStealthBombr() { const stealth = createStealthSpaceShip(); const bomer = createBomberSpaceShip(); return Object.assign({},stealth.bomer)}复制代码
使用Object.assign赋值
Object.assign只对对象本身可枚举的属性进行赋值,所以他不会对对象原型链上的属性和设置为不可枚举的属性进行赋值,这种做法对我们有好处
let numbers=[1,2,3];let objNumber=Object.assign({},numbers,{ sum:function(){ return this.reduce(function(a,b){ return a+b; }) }})console.log(objNumber[0]) //1console.log(objNumber[1]) //2console.log(objNumber[2]) //3objNumber.sum() // TypeError: this.reduce is not a function复制代码
上面报错的原因是,reduce方法是在数组numbers的原型链上,而不是它本身(本身只有三个属性值),我们可以将这三个值赋值给新对象,但是数组原型上的方法不能赋值给新对象, 我们继续改造,使用空数组进行赋值
let numbers=[1,2,3];let objNumber=Object.assign([],numbers,{ sum:function(){ return this.reduce(function(a,b){ return a+b; }) }})console.log(objNumber[0]) //1console.log(objNumber[1]) //2console.log(objNumber[2]) //3console.log(objNumber.sum()); //6复制代码