Object.create ,Object.assign

338 阅读3分钟

个人学习

Object.create

Object.create()  方法用于创建一个新对象,使用现有的对象来作为新创建对象的原型(prototype) Object.create有两个参数:

  • proto 新创建对象的原型对象
  • propertiesObject新创建对象的属性,默认值为undefined,为新创建的对象添加指定的属性值和对应的属性描述符。
属性描述符  `跟defineProperty的描述符对象一 一对应的`
value:属性值,
writable:是否可写(修改)的,默认为false,
configurable:是否可配置的(能否通过`delete`删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性,),默认为false,
enumerable:是否可遍历的,默认值为false

栗子

const obj = Object.create({a:1},{
    b:{
        value:2,
        writable:true,
        configurable:true,
        enumerable:true
    },
    c:{
        value:3,
        writable:true,
        configurable:true,
        enumerable:false
    }
})
console.log(obj)

image.png

// 遍历obj对象
// 由于obj.c属性设置enumerable为false 所以不可遍历出来
for (let key in obj){
    //Object.hasOwnProperty.call(obj,key) // 判断对象是否是原型上的,第一个参数是目标对象,第二个参数是key
    if(Object.hasOwnProperty.call(obj,key)){
        console.log('原型对象上的属性:',obj[key])
    }else{    
        console.log('obj对象的属性:',obj[key])
    }
}

image.png

创建没有原型对象的对象

// 通过传递null 实现
const obj = Object.create(null,{
    a:{
        value:1
    },
    b:{
        value:2
    }
    })
console.log(obj)

image.png

let obj = Object.create(null)
obj = {a:1,b:2} // 此时obj将会有原型,因为{a:1,b:2}  是由new Object构造出来的

Object.assign

Object.assign方法将源对象自有的(不可以是原型链的属性Object.hasOwnProperty返回true)中所有可枚举的属性复制到目标对象

两个参数

  • target:目标对象,接收源对象属性的对象
  • sources:源对象(可以是多个)

栗子

const test1 ={a:1,b:2}
const test2 ={c:3,d:4}
const test3 ={e:5,f:6}
const test4 = Object.assign(test1,test2,test3)
console.log(test1)
console.log(test4)

image.png

当在其中一个test用例的原型添加属性,这几个test用例的原型上都会有

const test1 ={a:1,b:2}
const test2 ={c:3,d:4}
const test3 ={e:5,f:6}
const test4 = Object.assign(test1,test2,test3)
test1.__proto__.x = 88
test3.__proto__.y = 99
Object.prototype.z = 100
console.log(test4)

image.png

是因为他们的原型都指向Object.prototype

      console.log(test1.__proto__ === Object.prototype)// true
      console.log(test1.__proto__ === test2.__proto__)// true
      console.log(test4.__proto__ === test2.__proto__)// true

将下面用例添加到v5对象中

// 如果源对象不是对象格式,会将其进行转换成对象格式,然后将源对象中可枚举的属性分配给 target
const v1 = 123,v2 = '123',v3 = true, v4 = function test(){}
/* 转化过程
v1 = new Number(123)
v2 = new String('123')
v3 = new Boolean(true)
v4 = new Function(test)
*/
// 其中v1,v3,v4的对象格式都是不可以枚举的
const v5 = Object.assign({},v1,v2,v3,v4)

image.png

Object.assing是深拷贝还是浅拷贝?

  • 对象的浅拷贝:浅拷贝是对象之间共用的一个内存地址,对象的变化相互影响。
  • 对象的深拷贝:简单理解深拷贝是将对象放到新的内存中,两个对象的改变不会相互影响。
// 此时是深拷贝
let target = Object.defineProperty({},'a',{
    value:1, // 
    writable:true
})

let res = Object.assign({},target,{b:3},{c:4})
// 不会影响到res
target.a = 10
console.log(res)
console.log(target)

image.png

现在修改一下a的值,将他的值改为引用数据类型

let target = Object.defineProperty({},'a',{
    value:{name:'张三',age:18}, // 改为引用数据类型
    writable:true
})

let res = Object.assign({},target,{b:3},{c:4})
target.a.name = '老王'
res.a.age = 30
// 此时值会互相改变
console.log(res)
console.log(target)

image.png

总结

对于Object.assign的浅拷贝还是深拷贝,是要看他复制的对象属性值的类型,当值是基本数据类型的时候此时Object.assign是深拷贝,不会相互影响,但当值是引用数据类型时,此时Object.assign就是浅拷贝,会互相影响

文章内容来自: csdn博主 b站up主前端小野森森