ES6-9【对象密封4种方式、assign、取值函数的拷贝】

一.对象密封的4种方式

(1).访问对象下的伪元素函数名

const obj = {
    get foo(){
        
    },
    set foo(x){
        
    }
}
log(obj.foo.name)//这样会报错因为打印Obj.foo == un

var descriptor = Object.getOwnPropertyDescriptor(obj,'foo');
log(descriptor.get.name);//打印get foo set访问也同理

(2).preventExtensions

阻止拓展

var obj = {a: 2};
log(Object.preventExtensions(obj));//{a: 2};
obj.b = 3;
log(obj);//{a:2}

查看是否可以拓展

log(Object.isExtensible(obj)); //false 不可拓展

特性

严格模式下会报错

会报错 不会静默失败

var obj = {a: 2};
Object.preventExtensions(obj);
Object.defineProperty(obj,'b',{
    value: 6
})

(3).defineProperty()特性

通过defindproperty配置描述符全部为false,通过点配置全部为true

(4).seal/isSealed

var obj = {a : 2};
Object.seal(obj); 
log(Object.isSealed(obj))//true 被密封 底层把所有的configurable改为false

(5).freeze/isFrozen

级别最高的方式

Object.freeze(obj);
log(Object.isFrozen(obj));//为true则代表已经冻结

深度冻结

对象里面是对象的情况就需要深度冻结了

function myFreeze(obj){
    Object.freeze(obj);
    for(var key in obj){
        if(typeof(obj[key]) === 'object' && obj[key] !== null){
            myFreeze(obj[key])
        }
    }
}

(6).is

log(+0 === -0);//true
log(NaN === NaN);//false
log(Object.is(NaN,NaN))//true
log(Object.is(+0,-0))//false

除去这两个方法外,基本一致

总结:共有4种冻结的方式:

1.描述符

2.preventExtensions

3.seal

4.freeze

二.assign

assign合并一个对象

(1).基础

let obj = {a: 1};
let tar = {};
let copy = Object.assign(tar,obj);
log(copy);//{a: 1}
log(copy === tar) //true 
log(copy === obj) //false
证明assign返回的对象就是原对象

(2).合并和覆盖的情况

合并
const tar = {a: 1};
const tar2 = {b: 2};
const tar3 = {c: 3};
Object.assign(tar,tar2,tar3)
log(tar);//{a:1,b:2,c:3}

覆盖
const tar = {a:1,b:1};
const tar2 = {b:2,c:2};
const tar3 = {c:3}
Object.assign(tar, tar2, tar3);
console.log(tar);//{a:1,b:2,c:3}

(3).第一个参数为原始值

无法进行合并因为没有包装类 null也是一样

Object.assign(undefined,{a:1});

有包装类的调用

var test = Object.assign(1,{a:1});
console.log(test);//Number{1,a:1}

(4).第二个参数为原始值

判断第二个值是否可枚举,然后合并

var test = Object.assign({a:1},'123');
log(test);
0: "1"
1: "2"
2: "3"
a: 1

如果第二个参数为boolean和number类型的都输出{}

var test = Object.assign([1,2,3,4],123);
console.log(test);[1,2,3,4]
var test = Object.assign([1,2,3,4],'321');
console.log(test);
["3", "2", "1", 4]


三.取值函数的拷贝

(1).基础

var obj = Object.create({foo:1},{
    bar:{
        value:2
    },
    baz:{
        value:3,
        enumberable:true
    }
})
log(obj)//
{
    baz:3
    bar:2
    __proto__:
        foo:1
}
//原型上的属性不管可不可以枚举的都不能拷贝
var copy = Object.assign({},obj);
log(copy);//{baz:3}

(2).symbol

可以生成不相等的原始值

var a = symbol();
var b = symbol();
log(a === b);//打印false

var a = symbol('a');
var b = symbol('a')
log(a == b)//打印false

拷贝

var test = Object.assign({a:'b'},{[Symbol('c')]:'d'});
log(test);
//{a:"b",Symbol(c):"d"}

(3).拷贝

浅拷贝

证明assign是浅拷贝

const obj1 = {a:{b:1}};
const obj2 = Object.assign({},obj1);
obj1.a.b = 2;
log(obj2);//{a:{b:2}}

证明是直接替换的没有单个深入替换

const target = {a:{b:'c',d:'e'}};
const sourse = {a:{b:'hello'}};
Object.assign(target, sourse);
log(target);//{a:{b:hello}}


数组替换

根据数组下标替换

var a = Object.assign([1, 2, 3],[4,5]);
log(a);//输出[4,5,3]

扩充

伪元素不可以扩充,下面能生效的原因是return值了

const sourse = {
    get foo(){
        return 1;
    }
}
const target = {};
Object.assign(target,sourse);
log(target); //{foo:1}

这样就不行
const sourse = {
    set foo(value){
        log(value);
    }
}
const tar = {};
Object.assign(tar,sourse);
log(tar);//{foo:un}

原型扩充可以扩充

var age = 1;
function Person(){}
Object.assign(Person.prototype,{
    eat(){
        
    },
    age
})
log(Person.prototype);
//{age:1,eat:eat()}

默认参数

通过三个参数来实现

const DEFAULT = {
    url: {
        host: 'www.baidu.com',
        port: 7070
    }
}
function test(option){
    option = Object.assign({},DEFAULT,option);
    log(option)
}
不传参
test();//{url:{host:'www.baidu.com',port:7070}}
传参
test({url:{port:8080}})//{url:{host:'www.baidu.com',port:8080}}

defineProperties()/getOwnPropertyDescriptors()

定义对象下多个变量的描述符/获取对象下所有变量的描述符

var obj = {}
Object.defineProperties(obj,{
    a:{
        value: true,
        writable: true
    },
    b:{
        value: 'hello',
        writable: false
    }
})
log(Object.getOwnPropertyDescriptors(obj));
//{
    a:
        configurable: false
        enumerable: false
        value: true
        writable:true
}
//{
    b:
        configurable: false
        enumerable: false
        value: 'hello'
        writable:true
}

伪属性的复制

这两个属性就是用来做这个的

getOwnPropertyDescriptors/defineProperties

问题的抛出
const sourse = {
    set foo(value){
        log(value);
    }
}
const tar = {};
Object.assign(tar,sourse);
log(tar);//{foo:un}

这样解决
Object.defineProperties(tar, Object.getOwnPropertyDescriptors(sourse));
log(Object.getOwnPropertyDescriptor(tar,'foo'));
//{
        configurable: true
        enumerable: true
        get:undefined
        value: f foo(value)
        writable:true
}

浅拷贝优化

var obj = {a:1, b:2, c:3}
const clone = Object.create(Object.getPrototypeOf(obj),Object.getOwnPropertyDescriptors(obj))
log(clone) {a:1,b:2,c:3}

//优化写法
const clone = (obj) => Object.create(Object.getPrototypeOf(obj),Object.getOwnPropertyDescriptors(obj))

总结:部署对象三种方式

1.const obj = Object.create(prot);

obj.foo = 123;

2.const obj = Object.assign(Object.create(prot),{

foo: 123

})

3.const obj = Object.create(prot,Object.getOwnPropertyDescriptors({

foo:123

}))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值