对象的基本创建
1、利用Object构造函数创建
const phoneOne = new Object();
phoneOne.name = '小米';
phoneOne.color = 'red';
phoneOne.say = function(){
console.log('小米');
}
console.log(phoneOne);
2、利用语法糖创建
利用语法糖创建对象其实内部也是利用 new Object 构造函数创建的过程
const phoneTwo = {
name:'华为',
color:'yellow',
say(){
console.log('华为')
}
};
console.log(phoneTwo);
对象属性的类型:
1、数据属性【在创建对象时默认生成,但通过方法可以进行修改】
数据属性包含一个保存数据值的位置。值会从这个位置读取,也会写入到这个位置。数据属性有4个特性描述它们的行为:
- [[Configurable]]:表示属性是否可以通过delete删除并重新定义,是否可以修改它的特性,以及是否可以把它改为访问器属性。默认情况下,所有直接定义在对象上的属性的这个特性都是true。
- [[Enumerable]]:表示属性是否可以通过for-in循环返回。默认情况下,所有直接定义在对象上的属性的这个特性都是true。
- [[Writable]]:表示属性的值是否可以被修改。默认情况下,所有直接定义在对象上的属性的这个特性都是true。
- [[Value]]:包含属性实际的值。指读取和写入属性值的位置。这个特性的默认值为undefined。
通过Object.defineProperty()方法去修改单个默认的对象属性
1、该方法接收三个参数:要添加属性的对象、要添加的属性名、属性的一个描述符对象。
2、在调用Object.defineProperty()时,configurable、enumerable和writable的值如果不指定,则都默认为false。
3、configurable设置为false,意味着这个属性不能从对象上删除。非严格模式下对这个属性调用delete没有效果,严格模式下会抛出错误。
4、一个属性被定义为不可配置之后【configurable为false后】,就不能再变回可配置的了。再次调用Object.defineProperty()并修改任何非writable属性会导致错误。
// 在调用Object.defineProperty()时,configurable、enumerable和writable的值如果不指定,则都默认为false。
const person = {};
Object.defineProperty(person,'name',{value:'小明'});
delete person['name'];
console.log(person.name); // 小明
for(let key in person) {
console.log(key,person[key]); // 不执行
}
person.name = '小红';
console.log(person.name) // 小明
// 自己制定该对象的数据属性
const person = {};
Object.defineProperty(person,'name',{
configurable:false,
enumerable:true,
writable:true,
value:'小明'
});
delete person['name'];
console.log(person.name); // 小明
for(let key in person) {
console.log(key,person[key]) // name 小明
}
person.name = '小红';
console.log(person.name) // 小红
//一个属性被定义为不可配置之后【configurable为false后】,就不能再变回可配置的了。再次调用Object.defineProperty()并修改任何非writable属性会导致错误。
const person = {};
Object.defineProperty(person,'name',{
configurable:false,
value:'小明'
});
Object.defineProperty(person,'name',{
enumerable:true
})
2、访问器属性
它们包含一个获取(getter)函数和一个设置(setter)函数,不过这两个函数不是必需的。在读取访问器属性时,会调用获取函数,这个函数的责任就是返回一个有效的值。在写入访问器属性时,会调用设置函数并传入新值,这个
函数必须决定对数据做出什么修改。
当一个对象只设置了getter方法则只能读取不能修改,当只设置了setter则该属性读取时在非严格模式下返回为undefined,严格模式下则报错。
const person = {};
Object.defineProperty(person,'name',{
get(){
return '小明被读取了'
}
});
console.log(person.name) //小明被读取了
person.name = '修改小明'
console.log(person.name) // 小明被读取了
const person = {};
Object.defineProperty(person,'name',{
set(value){
console.log('set执行',value)
}
});
console.log(person.name)
person.name = '小明'
console.log(person.name)
const person = {name:'小明'};
Object.defineProperty(person,'_name',{
get() {
return this.name
},
set(newValue){
this.name = newValue
}
})
console.log(person['_name']) // 小明
person['_name'] = '更改小明'
console.log(person['name']) // 更改小明
通过Object.defineProperties()方法去修改多个默认的对象属性
接收两个参数:要添加属性的对象、描述属性的对象
const person = {};
Object.defineProperties(person,{
name:{
configurable:false,
value:'小明'
},
age:{
writable:true,
value:10
}
})
读取对象的特征
Object.getOwnPropertyDescriptor() 【单个】
这个方法接收两个参数:属性所在的对象和要取得其描述符的属性名。
Object.getOwnPropertyDescriptors() 【多个】
const person = {name:'小明',age:20};
console.log(Object.getOwnPropertyDescriptor(person,'name'))
console.log(Object.getOwnPropertyDescriptors(person))
对象的新API
Object.assign()
1、同名的属性合并则后者会覆盖前者
2、 如果赋值期间出错,则操作会中止并退出,同时抛出错误。Object.assign()没有“回滚”之前赋值的概念,因此它是一个尽力而为、可能只会完成部分复制的方法。
4、对于string,Array 类型的数据则会将其拆分后进行合并。
const person = {name:'小明',age:20};
Object.assign(person,{name:'小红'})
console.log(person)
Object.assign(person,[1,3,5,6,7])
console.log(person)
Object.assign(person,'string')
console.log(person)
Object.assign(person,null)
console.log(person)
Object.assign(person,undefined)
console.log(person)
Object.assign(person,false)
console.log(person)
Object.is()
作用和 === (全等类似),但是对于某些特殊情况会进行更加准确的判断,返回值为 true/false。
console.log(0 === -0) // true
console.log(+0 === 0 ) // true
console.log(Object.is(0,-0)) // false
console.log(Object.is(+0,0)) // false
Object.keys()
拿到当前对象所有的的key组成的数组【Map除外】
const person = {name:'小红',age:10,color:'red'}
console.log(Object.keys(person)) // ['name', 'age', 'color']
Object.value()
拿到所有对象的所有的value值组成的数组【Map除外】
const person = {name:'小红',age:10,color:'red'}
console.log(Object.values(person)) // ['小红', 10, 'red']
Object.entries()
拿到对象每个key和value组成的数组 【Map除外】
const person = {name:'小红',age:10,color:'red'}
console.log(Object.entries(person))
Object.fromEntries()
将Map对象转为Object对象
const map = new Map([['name','小明']])
console.log(Object.fromEntries(map)) // {name: '小明'}
const map2 = new Map()
map2.set('name','小红')
console.log(Object.fromEntries(map2)) // {name: '小红'}
对象的扩展
对象的结构赋值
// 一般解构 + 初始化赋值
const {name,age,color = 'red'} = {name:'小明',age:10}
console.log(name,age,color) // 小明 10 red
// 深层解构 + 更改变量名称
const {user:{name:mingzi}} = {user:{name:'小明'}}
console.log(mingzi) // 小明
// 扩展运算符,实现对象浅拷贝
const obj = {...{name:'小明',age:20}}
console.log(obj) // {name: '小明', age: 20}
// 扩展运算符,实现获取对象剩余属性
const {name,...params} = {name:'小明',age:22,test:'测试'}
console.log(params) // {age: 22, test: '测试'}
对象属性的便利
(1)for…in
【循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性),包括实例属性和原型属性】
(2)Object.keys(obj)
【Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名】
(3)Object.getOwnPropertyNames(obj)
【返回一个数组,包含对象自身的所有属性(不含 Symbol
属性,但是包括不可枚举属性)的键名。】
(4)Object.getOwnPropertySymbols(obj)
【返回一个数组,包含对象自身的所有 Symbol 属性的键名。】
(5)Reflect.ownKeys(obj)
【Reflect.ownKeys返回一个数组,包含对象自身的(不含继承的)所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。】