截图无法放在上边, 可以自己保存代码进行运行查看效果;
对象的属性
属性分两种: 数据属性和访问器属性;
数据属性: 数据属性包含一个保存数据的位置, 值会从这份位置读取, 也会写入到这个位置, 数据属性有4个特征描述它们的行为.
概念:
[[Configurable]]:表示属性是否可以通过delete删除并重新定义,是否可以修改它的特性,以及是否可以把它改为访问器属性。默认情况下,所有直接定义在对象上的属性的这个特性都是true,如前面的例子所示。
[[Enumerable]]:表示属性是否可以通过for-in循环返回。默认情况下,所有直接定义在对象上的属性的这个特性都是true,如前面的例子所示。
[[Writable]]:表示属性的值是否可以被修改。默认情况下,所有直接定义在对象上的属性的这个特性都是true,如前面的例子所示。
[[Value]]:包含属性实际的值。这就是前面提到的那个读取和写入属性值的位置。这个特性的默认值为undefined。
可以通过defineProperty
对数据属性的控制.
const user = {
name: 'join',
age: 18,
};
// 对一个元素属性的控制
Object.defineProperty(user, 'name', {
value: 'join',
// 是否可以修改属性的值
writable: false,
// 是否可以通过遍历循环到
enumerable: false,
// 是否可以删除属性, 当属性被定义为不可配置后, 就不能在变回可配置
// 定义为false后, 不能在对此属性做任何配置的调整
configurable: false,
});
console.log(user.name);
user.name = 'li';
console.log(user.name);
delete user.name;
console.log(user.name);
// 同时对对象的多个元素做属性控制
Object.defineProperties(user, {
name: {
value: 'join',
writable: false,
enumerable: false,
},
age: {
value: '18',
writable: false,
enumerable: false,
},
});
获取属性特征
通过getOwnPropertyDescriptor
获取某个属性的特征
// 获取某个属性的所有特征
console.log(Object.getOwnPropertyDescriptor(user, 'name'));
// 获取某个属性的某个特征
console.log(Object.getOwnPropertyDescriptor(user, 'name').writable);
// 获取对象的所有属性的特征
console.log(Object.getOwnPropertyDescriptors(user));
禁止向对象添加属性
使用preventExtensions()
方法可以设置是否可以向对象添加属性;
使用isExtensible()
可以判断对象是否可以添加属性;
// 当返回值为true时, 可以添加属性
console.log(Object.isExtensible(user));
// 禁止向对象添加属性
const users = {
name: '丽丽',
age: 19,
};
console.log(users);
console.log(Object.getOwnPropertyDescriptors(users));
// 禁止向对象添加属性;
Object.preventExtensions(users); // 返回值为false
// 当isExtensible(users)为true时, 可以向对象添加属性
if (Object.isExtensible(users)) {
users.site = 'js';
}
console.log(users);
访问器属性
概念:
访问器属性不包含数据值。相反,它们包含一个获取(getter)函数和一个设置(setter)函数,不过这两个函数不是必需的。在读取访问器属性时,会调用获取函数,这个函数的责任就是返回一个有效的值。在写入访问器属性时,会调用设置函数并传入新值,这个函数必须决定对数据做出什么修改。访问器属性有4个特性描述它们的行为。
❑ [[Configurable]]:表示属性是否可以通过delete删除并重新定义,是否可以修改它的特性,以及是否可以把它改为数据属性。默认情况下,所有直接定义在对象上的属性的这个特性都是true。
❑ [[Enumerable]]:表示属性是否可以通过for-in循环返回。默认情况下,所有直接定义在对象上的属性的这个特性都是true。
❑ [[Get]]:获取函数,在读取属性时调用。默认值为undefined。
❑ [[Set]]:设置函数,在写入属性时调用。默认值为undefined。
const user = {
date: { name: 'lili', age: 19 },
get age() {
// 获取属性
return this.date.age + '岁';
},
set age(value) {
// 修改属性
if (typeof value != 'number' || value < 19 || value > 100) {
throw new Error('年龄格式错误');
}
this.date.age = value;
},
};
使用set可以保护访问器属性的变量;
使用访问器批量设置属性
const web = {
name: '开源',
url: 'www',
// 设置访问器属性
set site(value) {
console.log(value);
// 使用解构赋值
[this.name, this.url] = value.split(',');
},
get site() {
return `${this.name}的网址是${this.url}.`;
},
};
web.site = 'js,www.com';
console.log(web.site);
封闭对象
使用Object.seal()
封闭对象;
当对象处于封闭状态时, 当对象处于封闭状态时, 对象的"configurable" 特征为 false; 即不可添加属性, 不能删除对象的属性, 不能修改对象的特征;
'use strict';
const user = {
name: 'Lili',
age: 18,
};
// 封闭状态
Object.seal(user);
// 当对象处于封闭状态时, 对象的"configurable" 特征为 false
// 即不可添加属性, 不能删除对象的属性, 不能修改对象的特征
console.log(Object.isSealed(user)); // 当对象处于封闭状态时会返回true
console.log(JSON.stringify(Object.getOwnPropertyDescriptors(user), null, 2));
// 当对象为处于封闭状态时, 对对象进行修改
if (!Object.isSealed(user)) {
delete user.name;
user.site = '未处于封闭状态';
}
console.log(user);
冻结对象
可使用Object.freeze()
冻结对象;
const user = {
name: 'Lili',
age: 19,
};
// 未冻结属性
// Object.freeze(user);
console.log(Object.isFrozen(user)); // 冻结状态为true
console.log(JSON.stringify(Object.getOwnPropertyDescriptors(user), null, 2));
// 冻结状态下不能修改属性的值, 不能删除属性, 不能添加属性
if (!Object.isFrozen(user)) {
delete user.name;
user.site = '未冻结状态';
}
console.log(user);