Object对象的使用

创建对象
我们可以使用构造函数和对象字面量的形式创建Object类型的对象,例如:

// 使用字面量创建Object类型的对象
var obj1 = {
name: ‘张三’
};

// 使用构造函数创建Object类型的对象
var obj2 = new Object();
obj2.name = ‘李四’;
操作对象的属性
对象创建完成之后,我们可以随时随地为对象添加属性,也可以随时修改属性的值。假如,我们已经使用字面量的形式创建了obj1 对象:

var obj1 = {
name: ‘王五’
};
访问对象属性
访问属性最常用的方式是使用成员访问符(.)的方式,但也可以是方括号([])的形式访问:

// 使用成员访问符(.)
console.log(obj.name); // ‘王五’

// 使用中括号([])加属性名的形式
console.log(obj[‘name’]); // ‘王五’
添加对象属性
​​//给对象添加新属性
obj1.age = 23;
​obj1[‘gender’] = ‘男’;

修改对象属性
//修改已有属性的值
obj1.name = ‘赵六’;
obj1[‘age’] = 24;
删除对象属性
有的人可能会使用null值赋值给属性,这样并不能删除属性,仅仅是改变了属性的值。想要真正地将属性从对象中删除,需要使用delete操作符。

var person1 = {
name: ‘张三’
};

​// 并不能删除 name 属性
person1.name = null;

// name 属性还在
console.log(person1.name); //‘张三’

​// 使用delete操作符删除 name 属性
delete person1.name;

​// name 属性被完全删除了
console.log(person1.name); //‘undefined’
遍历对象属性
默认情况下,我们添加到对象上的属性都是可枚举的,这样的话我们就可以使用for-in循环遍历它们。

var obj = {
name: ‘张三’,
age: 23,
gender: ‘男’,
address: ‘鹤壁’
};

for (var propertyName in obj){
console.log(‘属性名:’ + propertyName);
console.log(‘属性值:’ + obj[propertyName]);
}

for-in循环每循环一次都会将一个属性名赋值给propertyName,直到所有的属性都被遍历一遍为止。

如果我们只是想获取一个对象中的所有属性名,可以使用Object.keys()方法。该方法会以数组的形式返回所有的属性名。

console.log(Object.keys(obj)); // [“name”, “age”, “gender”, “address”]
检查属性
由于对象的属性可以被随时随地被修改或删除,因此有时候我们需要检查对象的某个属性是否存在。使用下面的方式检查是不可靠的:

var person1 = {
name: ‘张三’
};

person1.name = ‘’; //或者null/undefined

if (person1.name) {
console.log(‘存在’);
} else {
console.log(‘不存在’);
}

使用这种方式可能会得不到正确的结果,如果属性的值是:对象,非空字符串,非零的数或者true,if条件语句会把它们转换成true。如果属性的值是:null,undefined,0,false,NaN,空字符串,if条件语句会把它们转换成false。检差对象中的属性是否存在的更可靠的方式是使用in操作符:

var person1 = {
name: ‘张三’
};

person1.name = ‘’; //或者null/undefined

if (‘name’ in person1) {
console.log(‘存在’); //‘存在’
} else {
console.log(‘不存在’);
}

属性分类
属性的类型分两种:一种是数据属性,一个种是访问器属性。数据属性用来存储一个值,比如所上个例子中的name。访问器属性不包含值,而是定义了一个get和set函数,当读取属性时,调用get函数,当写;入属性时,调用set函数。下面是一个使用字面量的形式定义访问器属性的语法:

var obj = {
firstName: ‘赵四’,
lastName: ‘尼古拉斯’,
get fullName(){
console.log(‘get方法被调用了’);
return this.lastName + ‘.’ + this.firstName;
},
set fullName(newName){
console.log(‘set方法被调用了’);
newName = newName.split(‘.’);
this.lastName = newName[0];
this.firstName = newName[1];
}
};

console.log(obj.fullName); // 读取属性,调用get函数
obj.fullName = ‘约翰尼.宋小宝’; // 写入属性,调用set函数

属性的内部特性
公共内部特性
所谓公共特性,指的是数据属性和访问器属性都具有的特性。

[[Enumerable]],决定了我们是否可以遍历该属性。
[[Configurable]],决定了该属性是否可以删除和改变(改变属性值和类型)。

默认情况下,我们在对象上添加的属性都是可枚举、可配置的。

获取属性的内部特性
获取属性的内部特性的方法有两个,分别是:

Object.getOwnPropertyDescriptor():获取对象中单个属性的内部特性
Object.getOwnPropertyDescriptors():获取对象中所有属性的内部特性

var obj = {
firstName: ‘赵四’,
lastName: ‘尼古拉斯’,
get fullName(){
console.log(‘get方法被调用了’);
return this.lastName + ‘.’ + this.firstName;
},
set fullName(newName){
console.log(‘set方法被调用了’);
newName = newName.split(‘.’);
this.lastName = newName[0];
this.firstName = newName[1];
}
};

//获取对象中单个属性的内部特性
var descriptor = Object.getOwnPropertyDescriptor(obj, ‘firstName’);
//获取对象中所有属性的内部特性
var descriptors = Object.getOwnPropertyDescriptors(obj);

数据属性的内部特性

  • Value,指定属性的值,例如,‘赵四’
  • Enumerable,决定了我们是否可以遍历该属性。
  • Configurable,决定了该属性是否可以删除和改变(改变属性值和类型)。
  • Writable,决定了该属性是否可以写入数据

访问器属性的内部特性

  • Get,当读取属性时,调用的函数。
  • Set,当写入属性时,调用的函数。
  • Enumerable,决定了我们是否可以遍历该属性。
  • Configurable,决定了该属性是否可以删除和改变(改变属性值和类型)。

定义属性的内部特性
定义属性的内部特性的方法也有两个,分别是:

  • Object.defineProperty():定义单个属性的内部特性。
  • Object.defineProperties():定义多个属性的内部特性。

使用Object.defineProperty()方法定义单个属性的内部特性

该方法接受3个参数:拥有被修改属性的对象、被修改的属性名、包含描述特性的对象。例如,我们将一个属性定义成不可枚举且不可配置,方法如下:

var person1 = {};

Object.defineProperty(person1, ‘firstName’, {
value: ‘克里斯蒂安’,
enumerable: false,
configurable: false,
writable: true
});

console.log(‘name’ in person1); //true
console.log(person1.propertyIsEnumerable(‘name’)); //false

Object.defineProperty(person1, ‘name’, {configurable: true}); // 报错

最后一行代码试图将name属性重新定义为可配置的,然而这会导致错误。你无法将一个不可配置的属性变成可配置。同样,在不可配置的情况下,试图将数据属性转变为访问器属性也会抛出错误,反之亦然。

使用Object.defineProperties()方法定义多个属性的内部特性。

该方法接受2个参数,第一个是属性所属的对象,第二个是包含被定义属性的对象。

var person1 = {};

Object.defineProperties(person1, {
firstName: {
value: ‘莱昂纳多’,
enumerable: true,
configurable: true,
writable: true
},
lastName: {
value: ‘小沈阳’,
enumerable: false,
configurable: false,
writable: false
},
fullName: {
get: function () {
return this.lastName + ‘.’ + this.firstName;
},
set: function (newName) {
newName = newName.split(‘.’);
this.lastName = newName[0];
this.firstName = newName[1];
},
enumerable: true,
configurable: true
}
});

禁止修改对象(对象的内部特性)
对象和属性一样也有指导其行为的内部特性。例如,[[Extensible]],它指明该对象本身是否可以被修改。默认情况下,我们创建的所有对象都是可扩展的,也就是说我们随时可以给对象添加新的属性。设置[[Extensible]]的值为false,我们就能禁止新属性的添加。接下来要讲的3种方法可以帮助我们锁定对象属性。
禁止扩展
第一种方法是使用Object.preventExtensions()创建一个不可扩展的对象。该方法接受1个参数,被禁止扩展的对象。对象被禁止扩展后,就永远不能再给它添加新的属性了。我们可以使用Object.isExtensible()检查对象是否被禁止扩展。代码如下:

var obj = {
firstName: ‘约翰尼’
};

// 检测对象是否可扩展
console.log(Object.isExtensible(obj)); // true

// 禁止对象扩展
Object.preventExtensions(obj);

// 检测对象是否可扩展
console.log(Object.isExtensible(obj)); // false

// 为对象添加新属性
obj.lastName = ‘宋小宝’;

console.log(‘lastName’ in obj); // false

创建obj后,这段代码先检查其[[Extensible]]特性,然后禁止其扩展。由于 obj 变得不可扩展,因此lastName永远无法被添加到obj上。
对象封印
对象封印是创建不可扩展对象的第二种方法。被封印的对象不仅不可扩展,而且其所有属性都不可配置。也就是说,不能给对象添加新属性,也不能删除已有属性或改变其类型,只能读写它的属性。

可以用Object.seal()方法来封印一个对象。对象被封印后,其[[Extensible]]特性被设置为false,其所有属性的[[Configurable]]特性被设置为false。可以用Object.isSealed()判断一个对象是否被封印。代码如下:

var obj = {
firstName: ‘约翰尼’
};

// 检测对象是否可扩展
console.log(Object.isExtensible(obj)); // true
// 检测对象是否被封印
console.log(Object.isSealed(obj)); // false

// 封印对象
Object.seal(obj);

// 封印对象之后,再次检测对象是否可扩展
console.log(Object.isExtensible(obj)); // false
// 封印对象之后,再次检测对象是否被封印
console.log(Object.isSealed(obj)); // true

// 为对象添加新属性(扩展对象)
obj.lastName = ‘宋小宝’;

// 由于被封印的对象是不可扩展的,因此 lastName 属性添加失败
console.log(‘lastName’ in obj); // false

// 删除对象的属性
delete obj.firstName;

// 由于被封印对象的所有属性都被设置成了不可配置([[Configurable]]特性被设置为false),因此 firstName 属性删除失败。
console.log(‘firstName’ in obj); // true

// 修改对象的属性
obj.firstName = ‘克里斯蒂安’;

// 由于被封印对象的属性还是可以写入的([[Writable]]特性值为 true),因此 firstName 属性修改成功
console.log(obj.firstName); // ‘克里斯蒂安’

// 检测对象的属性是否可以枚举([[Enumerable]]特性值为 true)
console.log(obj.propertyIsEnumerable(‘firstName’)); // true

这段代码封印了obj,因此不能在obj上添加或删除属性。所有被封印的对象都是不可扩展的对象,此时对象obj使用Object.isExtensible()方法将返回false,且试图添加 lastName会失败。
对象冻结
创建不可扩展对象的最后一种方法是冻结它。如果一个对象被冻结,则不能在其上添加或删除属性,不能改变属性类型,也不能写入任何数据属性。简而言之,被冻结对象是一个数据属性都为只读的被封印对象。我们可以使用Object.freeze()来冻结一个对象,用Object.isFrozen()来判断一个对象是否被冻结。代码如下:

var obj = {
firstName: ‘约翰尼’
};

// 检测对象是否可扩展;
console.log(Object.isExtensible(obj)); // true
// 检测对象是否被封印
console.log(Object.isSealed(obj)); // false
// 检测对象是否被冻结
console.log(Object.isFrozen(obj)); // false

// 冻结对象
Object.freeze(obj);

// 检测对象是否可扩展;
console.log(Object.isExtensible(obj)); // false
// 检测对象是否被封印
console.log(Object.isSealed(obj)); // true
// 检测对象是否被冻结
console.log(Object.isFrozen(obj)); // true

// 为对象添加新属性(扩展对象)
obj.lastName = ‘宋小宝’;

// 由于被冻结的对象是不可扩展的,因此 lastName 属性添加失败
console.log(‘lastName’ in obj); // false

// 删除对象的属性
delete obj.firstName;

// 由于被冻结对象的所有属性都被设置成了不可配置([[Configurable]]特性被设置为false),因此 firstName 属性删除失败。
console.log(‘firstName’ in obj); // true

// 修改对象的属性
obj.firstName = ‘克里斯蒂安’;

// 由于被冻结对象的所有属性都被设置成了不可写入([[Writable]]特性值为 false),因此 firstName 属性修改失败
console.log(obj.firstName); // ‘约翰尼’

// 检测对象的属性是否可以枚举([[Enumerable]]特性值为 true)
console.log(obj.propertyIsEnumerable(‘firstName’)); // true

这段代码冻结了obj。被冻结对象也被认为是不可扩展对象和被封印对象,所以Object.isExtensible()返回false,而Object.isSealed()则返回true。属性firstName无法被改变,所以试图对其赋值为’克里斯蒂安’的操作失败,依旧返回’约翰尼’。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值