Object
没有访问器时对象数据属性:
1、configurable 能否对该属性进行配置,比如能否修改属性值,默认true
2、enumerable 能否被枚举(数组,一个一个列出来供遍历),比如是否可以用for - in循环遍历属性,默认true
3、wriable 是否可写,是否能修改属性的值,默认true
4、value 包含属性的数据值,默认undefined
const obj = {};
obj.a = 1;//修改obj的value
Object.defineProperty(obj, 'b', {
configurable: true,
enumerable: true,
writable: false,
value: 2
})
Object.defineProperty(obj, 'b', {
configurable: true,//第一次设置false,第二次不允许再改为true。
enumerable: true,//不能被枚举,就不能遍历出来,但属性和值是可以直接使用的。
writable: true,//第一次false,第二次true属性值可以修改。
value: 2
})
obj.b = 3;//打印出来是3
访问器属性特征:
1、get 读取属性
2、set设置属性
3、configurable 能否对该属性进行配置,比如能否修改属性的值,默认true。
4、enumerable 是否能被枚举(数组,一个一个列出来供遍历),比如是否可以用for - in循环遍历属性,默认true
Object.defineProperty(obj, 'c', {
configurable: true,//可以省略
enumerable: true,//可以省略
set: function () {
},//访问器访问必须出现
get: function () {
return 123;
}//访问器访问必须出现
})
obj.c = 456//如果set内不设置,那么这个属性设置则无效。
console.log(
obj.c
);
Object.defineProperty(obj, 'c', {
configurable: true,//可以省略
enumerable: true,//可以省略
set: function (value) {
c = value;//不能使用this.c,this指向是整个Object.defineProperty
},//访问器访问必须出现
get: function () {
return c;
}//访问器访问必须出现
})
obj.c = 456
对象属性和访问器不能共存。
对象方法
Object.assgin():将所有可枚举的值从一个或多个源对象复制到目标对象,返回新的目标对象,可以创建对象。
Object.assgin(目标对象,源对象...)
将源对象的属性(可枚举,自由属性)合并到目标对象并返回。
assgin方法在合并属性的时候,只能合并自由属性,不能合并继承属性,只能合并可枚举属性,不能合成不可枚举属性。
通常,我们希望合并后的对象是一个新生成的对象,因此,通常将目标对象写为新对象:
const obj = Object.assign({},obj1,obj2...)//obj接收新对象。
const obj = Object.assign(null,obj1,obj2)
const 张三 = { a: 1 };
const 李四 = { b: 2 };
const 王五 = Object.assign(张三, 李四, 王五);//a:1 ,b:2 b:2 a:1 ,b:2 assign方法会直接修改a,并且返回值就是a
// const 王五 = Object.assign({},张三,李四); //合并属性,只能合并自由属性和可枚举属性,不能合并继承属性和不可枚举属性。
onsole.log(张三, 李四, 王五);
使用 Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组。
使用 Object.keys()方法会返回一个由一个给定对象的自身可枚举属性组成的数组。
使用Object.values()方法会返回一个由一个给定对象的自身可枚举属性的值组成的数组。
var obj = { a: 1, b: 2, c: 3 };
console.log(
Object.entries(obj)//[['a',1],['b',2],['c',3]]
)
for(let key of Object.keys(obj)){}
for(let value of Object.values(obj)){}
for(let [key,value] of Object.entries(obj)){}
使用Object.freeze()
方法可以冻结一个对象,只能读取,无法写入。(面试题经常考)
const obj = { a: 1, b: 2 };
Object.freeze(obj);
obj.b = 222;
console.log(obj.b)//2
//面试题经常考
使用Object.getOwnPropertyDescriptor()方法可以查看这些特征。
const obj = {a:1,b:2};
console.log(
//{value: 1, writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyDescriptor(obj,'a');
)
使用Object.getOwnPropertyNames()
方法可以获得对象属性名称形成的数组。
const obj = {a:1,b:2};
console.log(
Object.getOwnPropertyNames(obj);//["a","b"]
)
使用Object.getOwnPropertySymbols()方法可获得对象属性名称中所有Symbol类型形成的数组。Symbol类型表示独一无二的值,Symbol可以作为属性名称(key),但是常规方法都会忽略它
使用Object.getPrototypeOf()方法可以获得当前对象的原型。
使用Object.setPrototypeOf()方法为参数对象设置原型,返回该参数对象。
const a = { x: 1 };
const b = { y: 2 };
Object.setPrototypeOf(b, a);
//b.__proto__ === a true
//Object.getPrototypeOf(b) === a true
//设置对象b继承自对象a。
使用Object.create()方法可以返回一个对象,该对象以参数对象为原型,完全继承原型对象的属性。
const a = { a: 1, b: 2, c: 3 };
const b = Object.create(a);
b.b = 123;
console.log(b.a, b.b, b.c);
Object.create(null);
通过Object.create(null)生成的对象不是继承自object对象,没有常规对象的属性和方法,只用来存储数据。 Object.create(null)很轻,可以用来存储大型数据,会加快访问速度。
使用Object.defineProperty(对象,属性,属性特征)方法可以设置对象属性及属性的访问器
defineProperty 设置对象的属性时,如果设置为访问器,则不能同时设置静态属性。
defineProperty 设置属性或访问器时,除了get、set之外,其他的属性默认是false
Object.defineProperty(obj,'a'{
get:function(){}
set:function(){}
})
遍历和区别
const 李四 = { x: 1 }
const 张三 = Object.create(李四);
张三.a = 1;
Object.defineProperty(张三, 'b', {
value: 2,
configurable: true,
enumerable: false,
writable: true,
})
for in
:使用for..in循环时,返回的是所有能够通过对象访问的、可枚举的属性
,既包括存在于实例中的属性,也包括存在于原型中的属性。
for (let item in 张三) {
console.log(item);//a,x
}
Object.keys()
:用于获取对象自身所有的可枚举的属性值
,但不包括原型中的属性
,然后返回一个由属性名组成的数组
for (let item of Object.keys(张三)) {
console.log(item);//a
}
Object.getOwnPropertyNames()
:方法返回对象的所有自身属性的属性名
(包括不可枚举的属性
)组成的数组,但不会获取原型链上的属性
for (let item of Object.getOwnPropertyNames(张三)) {
console.log(item);//a,b
}
区别
for in 可以获取:自身属性+继承的属性,排除不可枚举的。
Object.keys() 可以获取: 自身的属性,排除继承的和不可枚举的。
Object.getOwnPropertyNames() 可以获取:自身的属性(包括不可枚举的),排除的是继承的属性。
深拷贝和浅拷贝
浅拷贝是只拷贝对象的引用,深拷贝是引用及数据都拷贝。
当对象的值还是对象时,拷贝的过程如果只对第一级深拷贝,之后都是浅拷贝,我们叫做浅拷贝,对所有级别都进行深拷贝,才叫深拷贝。
深拷贝的方式:JSON.parse(JSON.stringify(obj))
自己使用递归或其他方式逐级做深拷贝
浅拷贝:[...arr] arr.concat([]) Object.assign({},obj1) {...obj1}