一、对象常量,不可修改、删除和添加属性
(1)通过Object.defineProperty设置不可修改和删除的属性。
(2)通过Object.preventExtensions(禁止拓展增加属性),可以通过Object.isExtensible来判断拓展性
let obj = {a : 2}Object.preventExtensions(obj)obj.b = 321console.log(obj) // => {a : 2}console.log( Object.isExtensible(obj) ) // => false
**给对象添加属性的时候,推荐使用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严格相等没区别。
Object.is(NaN, NaN) // => trueObject.is(+0, -0) // => trueObject.is(undefined , null) // => false, 相等运算符中,undefined和null不转化,直接相等。
三、Object.assign
用于对象合并,将源对象(source)自身且可枚举属性浅拷贝到目标对象上。参数为 目标对象 + 源对象s
let target = {},a = {a : 'a'},b = {b : 'b'};Object.assign(target, a, b);console.log(target)
(1)同名属性情况:后者属性替换前者。
let target = { a: {b : 'b', c :'c'} },source = { a: { b: 'c' } };Object.assign( target, source ) // => { a: { b: 'c' } }
(2)如果参数为非对象,系统会将参数转化为对象
a.如果null和undefined作为目标对象参数,没有对应包装类,会报错
b.如果null和undefined作为源对象参数,系统会跳过不会报错
c.非对象值作为源对象参数时,只有字符串会以数组形式,合并到目标对象,因为只有字符串包装类会产生可枚举属性。
(3)数组处理,下标元素替换
let arr1 = [1, 2, 3],arr2 = [4, 5];Object.assign(arr1, arr2) // => [4, 5, 3]
(4)取值函数(getter)<br />Object.assign会先取值函数求值,再拷贝属性
let target = {},a = {get foo (){return 123}};Object.assign(target, a) // => {foo: 123}
(5)用处<br />a.给对象添加属性
class Super{constructor(x, y){Object.assign(this, {x, y})} // 给Super实例添加x,y属性}
b.给对象添加方法
function call(val){console.log(call)}function say(val){console.log(val)}Object.assign(Super.prototype,{call,val})
c.合并多个对象
const options = Object.assign({}, defaultOptions, this.options)//合并多个源对象属性返回新对象'const merge = (target, ...sources) => Object.assign(target,...sources)
d.设置默认选项
const defaulOptions = {url: 'google',port:'80'}myOptions = {url : 'otherUrl'}const UltimateOption = Object.assign({}, defaultOptions, myOptions)////////////////////////////////如果配置项包含对象,默认配置项可能会被覆盖const defaulOptions2 = {url: {address: 'baidu',port:'80'}}myOptions2 = {url : {address: 'baidu'}}const UltimateOption2 = Object.assign({}, defaultOptions2, myOptions2)// url : {address: 'baidu'} ,默认端口号消失,失效
设置默认值时,需要注意,配置项尽量为原始值,不然源对象属性会把默认值对象属性覆盖,导致默认值失效。
四、Object.defineProperties,给对象定义多个属性
(1)Object.defineProperties,参数:
object,
descriptors,包含一个或多个属性的描述对象。
let o = {};Object.defineProperties(o,{key1:{value: 123,enumerable : true,wirtable : true,configurable : true},key2: {value: 321}});console.log(o)
(2)Object.getOwnPropertyDescriptors 获取对象所有自身的属性描述对象
let o = {};Object.defineProperties(o,{key1:{value: 123,enumerable : true,wirtable : true,configurable : true},key2: {value: 321}});console.log(Object.getOwnPropertyDescriptors(o))
(3)拷贝对象getter和setter的方法<br />思路:通过Object.defineProperties定义属性
let o = {set name(val){console.log('name')}}//如果直接查找setter,获取到的是setter函数执行的结果//如果通过Object.assign,属性赋值的是setter函数执行返回值const copyObj = {};Object.defineProperties(copyObj, Object.getOwnPropertyDescriptors(o))
五、浅克隆并实现原型链继承的方式
Object.create有两个参数,
prototype, 对象原型
desciptors 属性描述对象
新对象属性也是浅拷贝来的
let a = {set name (val){console.log(123)},obj : {age:123,hobby : 'drinking'}}let newA = Object.create(Object.getPrototypeOf(a), Object.getOwnPropertyDescriptors(a));console.log(newA)
