对象的属性特性
读取属性的特性
Object.getOwnPropertyDescriptor(); 返回指定对象指定属性的描述特性,第一个参数是对象,第二个参数是属性名
Object.getOwnPropertyDescriptors(); 返回指定对象所有属性的描述特性,参数是对象。
读取对象上的属性
Object.getOwnPropertyNames(); 返回指定对象所有属性名,参数是对象。
数据属性和访问器属性
对象的属性可以分为数据属性和访问器属性,它们的描述特性是不同的。
① 数据属性
数据属性包含一个数据值的位置,我们定义对象时设置的属性都是数据属性。
数据属性有如下 4 个特性:
1)Configurable
:可配置性,表示能否通过 delete 删除属性,能否修改属性的特性,能否把属性修改为访问器属性,默认值为 true。
2)Enumerable
:可枚举性,表示能否通过 for-in 循环返回,默认值为 true。
3)Writable
:可写性,表示能否修改属性的值,默认值为 true。
4)Value
:值,这个属性的数据值。读取属性值的时候,从这个位置读;写入属性值的时候,把新值保存在这个位置。默认值为 undefined。
// user 对象的属性的特性
console.log(Object.getOwnPropertyDescriptor(user, 'address'));
console.log(Object.getOwnPropertyDescriptor(user, 'say'));
console.log(Object.getOwnPropertyDescriptors(user));
console.log('');
console.log(Object.getOwnPropertyDescriptor(arr, 'length'));
console.log(Object.getOwnPropertyDescriptors(arr));
console.log('');
console.log(Object.getOwnPropertyDescriptor(window, 'name'));
可以通过下面方式设置属性的特性:
var person = {
name:'高晓乐';
address:'上海';
};
Object.defineProperty(person, "name", {
writable: false,
value: "Nicholas"
});
② 访问器属性
访问器属性不包含数据值;它们包含一对儿 getter 和 setter 函数。在读取访问器属性时,会调用 getter 函数,这个函数负责返回有效的值;在写入访问器属性时,会调用 setter 函数并传入新值,这个函数负责决定如何处理数据。
访问器属性有如下 4 个特性:
1)Configurable
:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为数据属性。
2)Enumerable
:表示能否通过 for-in 循环返回属性。
3)Get
:在读取属性时调用的函数。默认值为 undefined。
4)Set
:在写入属性时调用的函数。默认值为 undefined。
可以通过如下方式为对象设置访问器属性:
相当于一个拦截器
var book = {
// 下划线设置属性,不对外公开
_year: 2004,
edition: 1
};
Object.defineProperty(book, "year", {
get: function(){
return this._year;
},
set: function(newValue){
//在这里设置条件
if (newValue > 2004) {
this._year = newValue;
this.edition += newValue - 2004;
}
}
});
Object定义多个属性方法
Object.defineProperties()
Object.defineProperties()
这个方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。
Object.defineProperties(obj, props)
/*
obj 在其上定义或修改属性的对象。
props 要定义其可枚举属性或修改的属性描述符的对象。
props对象中的 "属性" 可配置如下键值:
configurable:true/false,
enumerable:true/false,
value:"", //与属性关联的值。可以是任何有效的JavaScript值(数字,对象,函数等)。
writable:true/false,
get:function(){
//当获取 "属性" 时,会自动调用 get 方法
//get方法体中 return 什么,属性值就是什么
},
set:function(val){
//当设置 "属性" 时,会自动调用 set 方法
}
*/
var book = {
};
Object.defineProperties(book, {
_year: {
value: 2004
},
edition: {
value: 1
},
year: {
get: function(){
return this._year;
},
set: function(newValue){
if (newValue > 2004) {
this._year = newValue;
this.edition += newValue - 2004;
}
}
}
});
// 创建对象
const user = {
name: '小乐',
_age: 0
};
// 给 user 添加多个属性并设置属性的特性
Object.defineProperties(user, {
address: {
enumerable: false,
configurable: false,
writable: false,
value: '上海'
},
age: {
configurable:true,
enumerable:false,
set: function(val) {
val = +val;
if (val >= 0 && val <= 200) {
this._age = val;
}
},
get: function() {
return this._age;
}
}
});
console.log(user.address); //上海
console.log(user.age); //0
Object.create()
Object.create()
可以在创建新对象的同时,给对象添加属性并设置特性:
Object.create(Objec.prototype, {
// foo 是一个常规数据属性
foo: {
writable: true,
configurable: true,
value: "hello",
},
// bar 是一个访问器属性
bar: {
configurable: false,
get() {
return 10;
},
set(value) {
console.log("Setting `o.bar` to", value);
},
});
创建一个对象,原型是Array,并设置数据属性,
const arr = Object.create(Array.prototype, {
0: {
configurable: false,
enumerable:false,
writable:true,
value: '北京'
},
1: {
configurable: false,
enumerable:false,
writable:true,
value: '上海'
},
address: {
enumerable: false,
configurable: false,
writable: false,
value: '上海'
},
age: {
configurable:true,
enumerable:false,
set: function(val) {
},
get: function() {
return 100
}
}
});
console.log(arr);
Class定义访问器方法
//定义类
class Person {
//定义属性
#firstName = '尼古拉斯';
#lastName = '赵四';
//当获取fullName属性值的时候 自动调用
get fullName() {
return this.#firstName + '·' + #this.lastName;
}
//当设置fullName属性值的时候 自动调用 接受一个参数,是要给fullName属性设置的新值
set fullName(val) {
this.#firstName = val.split('·')[0];
this.#lastName = val.split('·')[1];
}
}
class Product {
// 数据属性
name = '高小乐';
address = '上海';
#age = 0;
// 访问器属性
set age(val) {
val = +val;
if (val >= 0 && val <= 200) {
this.#age = val;
}
};
get age() {
return this.#age;
}
}
// 实例化
const p = new Product();
console.log(p);
p.age = 124;
p.age = 1240;
console.log(p.age);
对象的封闭和冻结
① 封闭对象
对象封闭之后,阻止添加新属性并将所有现有属性标记为不可配置。
Object.seal() 封闭对象
Object.isSealed() 判断对象是否被封闭
// 定义数组
const arr = [10,20,30,40,50];
arr.name = '高小乐';
arr.address = '上海';
封闭对象
Object.seal(arr);
console.log('对象是否被封闭:', Object.isSealed(arr));
console.log('对象是否被冻结:', Object.isFrozen(arr));
console.log('');
// 封闭之后 不能添加新属性 旧的属性不可配置
// 冻结之后 不能添加新属性 旧的属性不可配置 旧属性不可写
arr.age = 100;//不可以
delete arr.name;//不可以
arr[0] = 250; //可以更改属性的值
arr.address = '北京';//可以更改属性的值
console.log(arr);
② 冻结对象
对象冻结之后,阻止添加新属性并将所有现有属性标记为不可配置,不能修改已有属性的值,该对象的原型也不能被修改。
Object.freeze() 冻结对象
Object.isFrozen() 判断对象是否被冻结
// 定义数组
const arr = [10,20,30,40,50];
arr.name = '高小乐';
arr.address = '上海';
// 冻结对象
Object.freeze(arr);
console.log('对象是否被封闭:', Object.isSealed(arr));
console.log('对象是否被冻结:', Object.isFrozen(arr));
console.log('');
// 封闭之后 不能添加新属性 旧的属性不可配置
// 冻结之后 不能添加新属性 旧的属性不可配置 旧属性不可写
arr.age = 100;//不可以
delete arr.name;//不可以
arr[0] = 250; //不可以
arr.address = '北京';//不可以
console.log(arr);