js对象属性
属性的类型
js对象的分两种:**数据属性 **和 访问器属性
(一) 数据属性
顾名思义,数据属性就是用来直接保存数据的属性,一般情况下,我们都只会定义和操作数据属性
数据数据的四个特性
- configurable 定义属性是否可以为 delete 重新定义或修改为访问器属性,默认 true
- enumerable 定义属性是否可以被枚举,默认 true
- writable 定义属性是否可以被修改,默认 true
- value 属性的值
显性设置属性的参数
- writable 测试
const person = {};
Object.defineProperty(person,'name',{
writable: false, // 不可以被修改
value: "小明"
});
console.log(person.name); // 小明
// 尝试修改 name 值失败
person.name = "大明"
// 还是 小明
console.log(person.name); // 小明
- configurable 测试,configurable 为 false 的定义是不能修改 该属性的 4 个值
const person = {};
Object.defineProperty(person, 'name', {
configurable:false,// 不能重新定义属性
value: "小明"
});
try{
// delete person.name
Object.defineProperty(person, 'name', {
configurable:true, // 改为 true 会报错,依旧是 false 的话就不会报错
value: "小明"
});
} catch(err){
console.log(err);
}
// configurable 为 false 的定义是不能修改 该属性的 4 个值
// 修改属性的value值,不会成功,但不会报错
person.name = "大明"
console.log(person.name); // 小明
(二 )访问器属性
访问器属性,可以有点陌生,访问器就是来操作(获取 getter,设置 setter)数据属性的
const person = {
firstName_: '李', // 数据属性,私有属性(只是这样定义而已(规范),外部依旧可以访问)
lastName_: '小龙', // 数据属性,私有属性
set name(name) {
this.firstName_ = name.slice(0, 1)
this.lastName_ = name.slice(1,3)
},
get name() {
return this.firstName_ + this.lastName_
}
}
console.log(person);
console.log(person.name); // 李小龙
person.name = "黄飞鸿"; // 修改了 name, 实际是修改 fistName_ 和 lastName_
console.log(person.name); // 黄飞鸿
上面 name 就是访问器,可以通过它来一次性获取和设置两个 firstName_ 和 lastName_ 的组合值
Object.defineProperties 定义多个属性值
const book = {};
Object.defineProperties(book, {
// 数据属性
year_: {
value: 2017,
configurable: true,
writable:true
},
// 数据属性
edition: {
value: 1,
configurable: true,
writable:true
},
// 访问器属性, MVVM 框架的 watch 属性监听器的基础
year: {
//value: 2018, // 不能同时 将属性定义数据属性和访问器属性
get() {
return this.year_;
},
set(newValue) {
if(newValue > 2017) {
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
}
})
console.log(book.year, book.edition); // 2017 1
book.year = 2019;
console.log(book.year, book.edition); // 2019 3
不能同时 将属性定义数据属性和访问器属性
year: {
value: 2018, // 不能同时 将属性定义数据属性和访问器属性
get() {
return this.year_;
},
set(newValue) {
if(newValue > 2017) {
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
}
(三)注意!!!使用defineProperty 或 defineProperties 定义 属性时 configurable、writable、enumerable 默认值为 false
// Object.getOwnPropertyDescriptor 和 Object.getOwnPropertyDescriptors
const person = {};
Object.defineProperty(person, 'name', {
value: '小明'
})
const descriptor = Object.getOwnPropertyDescriptor(person, 'name')
console.log(descriptor);
(四)属性枚举
实例准备
const animal = {
leg: 2,
head: 1,
hand: 2
}
const person = {}
Object.defineProperties(person, {
name: {
value: '小明',
enumerable: true
},
height: {
value: 180,
enumerable: true
},
weight: {
value: 70,
enumerable: true
},
sex: {
value: '男',
enumerable: true
},
age: {
value: 22,
enumerable: false // 不可被枚举
}
})
Object.setPrototypeOf(person, animal)
console.log(person);
-
for…in 语句
for...in
循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。for(let prop in person){ console.log(prop+':'+person[prop]); }
输出结果:属性age没有输出,因为它的enumertable特性是 false, 原型属性leg, head, hand也输出了
-
Object.keys()
Object.keys
返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。const keys = Object.keys(person); console.log(keys);
输出结果:只有对象自身的可枚举属性,不可枚举属性age没输出,原型属性也没输出
-
Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames
返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。const propNames = Object.getOwnPropertyNames(person); console.log(propNames);
输出结果:对象自身所有属性都输出了
-
Object.getOwnpropertySymbols()
Object.getOwnPropertySymbols(obj) 返回一个数组,包含对象自身的所有 Symbol 属性的键名。
// 添加 symbol 属性 const idSymbol = Symbol("id"); Object.defineProperty(person, idSymbol, { value: 1 }) console.log(person); const propSymbols = Object.getOwnPropertySymbols(person); console.log(propSymbols);
输出结果:只返回对象自身的 symbol(id) 属性名
- Reflect.ownKeys(obj)
Reflect.ownKeys
返回一个数组,包含对象自身的(不含继承的)所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
const ownKeys = Reflect.ownKeys(person);
console.log(ownKeys);
输出结果:不可枚举属性 age 和 symbol 属性 symbol(id)都输出了
属性枚举特性汇总,打钩表示会被输出
方法 | 可枚举属性 | 不可枚举属性 | 继承属性 | symbol属性 |
---|---|---|---|---|
for…in… | √ | √ | ||
Object.keys | √ | |||
Object.getPropotyNames | √ | √ | ||
Object.getPropotySymbols | √ | |||
Reflect.ownKeys | √ | √ | √ |