一、对象常量,不可修改、删除和添加属性
    (1)通过Object.defineProperty设置不可修改和删除的属性。
    (2)通过Object.preventExtensions(禁止拓展增加属性),可以通过Object.isExtensible来判断拓展性

    1. let obj = {
    2. a : 2
    3. }
    4. Object.preventExtensions(obj)
    5. obj.b = 321
    6. console.log(obj) // => {a : 2}
    7. console.log( Object.isExtensible(obj) ) // => false
    1. **给对象添加属性的时候,推荐使用Object.defineProperty**.因为对象不可拓展的时候,通过直接给对象属性赋值的方式在非严格模式下会**静默失败但不报错**,使用**Object.defineProperty的方式就会有报错提示(obj is not extensible)**。

    (3)密封对象, Object.seal,阻止对象添加新属性,原有属性configurable改为false,不改变writable属性
    可通过Object.isSealed来判断是否被密封。

    (4)Object.freeze用来冻结对象,禁止添加、修改、删除对象属性,但是引用类型值可以修改,需要递归冻结引用类型值

    (5)Object.preventExtensions、Object.defineProperty、Object.freeze区别
    a. Object.defineProperty 设置属性是否可修改和删除,针对对象属性
    b. Object.preventExtensions 用来禁止给对象属性添加新属性,针对对象
    c. Object.seal 禁止添加新属性,将属性configurable改为false,不改变原有属性writable,针对对象
    d. Object.freeze 用来冻结对象,禁止添加、修改、删除对象属性,但是引用类型值可以修改,需要递归冻结引用类型值,针对对象
    功力排行榜:Object.preventExtensions < Object.seal < Object.freeze
    二、es6中Object新增方法
    (1)Object.is
    es5中有两种相等运算符, ‘==’和’===’,前者会转化数据类型,后者严格相等但是NaN和NaN、+0 和 -0不相等。
    es6中新增一种相等判断,只要值相等就返回true,出了NaN和NaN, +0 和 -0两种情况,和es5严格相等没区别。

    1. Object.is(NaN, NaN) // => true
    2. Object.is(+0, -0) // => true
    3. Object.is(undefined , null) // => false, 相等运算符中,undefined和null不转化,直接相等。

    三、Object.assign
    用于对象合并,将源对象(source)自身且可枚举属性浅拷贝到目标对象上。参数为 目标对象 + 源对象s

    1. let target = {},
    2. a = {a : 'a'},
    3. b = {b : 'b'};
    4. Object.assign(target, a, b);
    5. console.log(target)

    (1)同名属性情况:后者属性替换前者。

    1. let target = { a: {b : 'b', c :'c'} },
    2. source = { a: { b: 'c' } };
    3. Object.assign( target, source ) // => { a: { b: 'c' } }

    (2)如果参数为非对象,系统会将参数转化为对象
    a.如果null和undefined作为目标对象参数,没有对应包装类,会报错
    b.如果null和undefined作为源对象参数,系统会跳过不会报错
    c.非对象值作为源对象参数时,只有字符串会以数组形式,合并到目标对象,因为只有字符串包装类会产生可枚举属性。

    (3)数组处理,下标元素替换

    1. let arr1 = [1, 2, 3],
    2. arr2 = [4, 5];
    3. Object.assign(arr1, arr2) // => [4, 5, 3]
    1. 4)取值函数(getter)<br />Object.assign会先取值函数求值,再拷贝属性
    1. let target = {},
    2. a = {
    3. get foo (){
    4. return 123
    5. }
    6. };
    7. Object.assign(target, a) // => {foo: 123}
    1. 5)用处<br />a.给对象添加属性
    1. class Super{
    2. constructor(x, y){
    3. Object.assign(this, {x, y})} // 给Super实例添加x,y属性
    4. }
    1. b.给对象添加方法
    1. function call(val){
    2. console.log(call)
    3. }
    4. function say(val){
    5. console.log(val)
    6. }
    7. Object.assign(Super.prototype,{call,val})

    c.合并多个对象

    1. const options = Object.assign({}, defaultOptions, this.options)
    2. //合并多个源对象属性返回新对象'
    3. const merge = (target, ...sources) => Object.assign(target,...sources)

    d.设置默认选项

    1. const defaulOptions = {
    2. url: 'google',
    3. port:'80'
    4. }
    5. myOptions = {
    6. url : 'otherUrl'
    7. }
    8. const UltimateOption = Object.assign({}, defaultOptions, myOptions)
    9. //////////////////////////////
    10. //如果配置项包含对象,默认配置项可能会被覆盖
    11. const defaulOptions2 = {
    12. url: {
    13. address: 'baidu',
    14. port:'80'
    15. }
    16. }
    17. myOptions2 = {
    18. url : {
    19. address: 'baidu'
    20. }
    21. }
    22. const UltimateOption2 = Object.assign({}, defaultOptions2, myOptions2)
    23. // url : {address: 'baidu'} ,默认端口号消失,失效
    1. 设置默认值时,需要注意,配置项尽量为原始值,不然源对象属性会把默认值对象属性覆盖,导致默认值失效。

    四、Object.defineProperties,给对象定义多个属性
    (1)Object.defineProperties,参数:
    object,
    descriptors,包含一个或多个属性的描述对象。

    1. let o = {};
    2. Object.defineProperties(o,{
    3. key1:{
    4. value: 123,
    5. enumerable : true,
    6. wirtable : true,
    7. configurable : true
    8. },
    9. key2: {
    10. value: 321
    11. }
    12. });
    13. console.log(o)

    (2)Object.getOwnPropertyDescriptors 获取对象所有自身的属性描述对象

    1. let o = {};
    2. Object.defineProperties(o,{
    3. key1:{
    4. value: 123,
    5. enumerable : true,
    6. wirtable : true,
    7. configurable : true
    8. },
    9. key2: {
    10. value: 321
    11. }
    12. });
    13. console.log(Object.getOwnPropertyDescriptors(o))
    1. 3)拷贝对象gettersetter的方法<br />思路:通过Object.defineProperties定义属性
    1. let o = {
    2. set name(val){
    3. console.log('name')
    4. }
    5. }
    6. //如果直接查找setter,获取到的是setter函数执行的结果
    7. //如果通过Object.assign,属性赋值的是setter函数执行返回值
    8. const copyObj = {};
    9. Object.defineProperties(copyObj, Object.getOwnPropertyDescriptors(o))

    五、浅克隆并实现原型链继承的方式
    Object.create有两个参数,
    prototype, 对象原型
    desciptors 属性描述对象
    新对象属性也是浅拷贝来的

    1. let a = {
    2. set name (val){
    3. console.log(123)
    4. },
    5. obj : {
    6. age:123,
    7. hobby : 'drinking'
    8. }
    9. }
    10. let newA = Object.create(Object.getPrototypeOf(a), Object.getOwnPropertyDescriptors(a));
    11. console.log(newA)