一、创建对象
// 创建对象的三种方式
var obj1 = {};
var obj2 = new Object();
function Person(){};
var obj3 = new Person();
二、操作对象
var obj = {
fname: '张三'
}
// 访问
console.log(obj.fname); // 张三
console.log(obj['fname']); // 张三
console.log(obj.age); // 未定义属性打印undefined
// 增加
obj.age = 19;
obj['gender'] = 'male';
// 修改
obj.age += 1;
obj['age'] += 1;
console.log(obj.age); // 21
// 删除
delete obj.gender;
// 遍历
for(var key in obj){
console.log(obj[key]);
}
使用Object.keys()获取包含所有键的数组
三、检查属性是否存在
(1)利用不存在的属性返回undefined
var obj = {
fname: '张三'
}
if(obj.age === undefined){
console.log('不存在!');
}
(2)in操作符检查属性是否存在,返回布尔值
var obj = {
fname: '张三'
}
console.log('age' in obj); // false
(3)使用hasOwnProperty()方法检查属性是否存在,返回布尔值
var obj = {
fname: '张三'
}
console.log(obj.hasOwnProperty('age')); // false
in和hasOwnProperty()的区别:in在当前对象中查找不到该属性时,会沿着原型链向上继续查找;hasOwnProperty()只会在对象自身中查找;
var obj = {
fname: '张三'
}
console.log('toString' in obj); // true
console.log(obj.hasOwnProperty('toString')); // false
四、属性的分类
对象的属性可以分为:数据属性和访问器属性。数据属性就是用来存储数据的;访问器属性是定义了get()和set()方法,当访问属性时会调用get()方法,设置属性时会调用set(参数)方法。get()和set()不必同时出现,根据需求设置。
var obj = {
fname: '张三',
get getName(){
return this.fname + '就是张三啊!';
},
// 形参必须有
set setName(name){
return this.fname = name;
}
}
console.log(obj.getName); // 张三就是张三啊!
obj.getName = '李四'; // get只能访问,不可以修改,没有任何效果
obj.setName = '王五';
console.log(obj.fname); // 王五
五、属性的特性
(1)数据属性和访问器属性的公共特性:
- [[enumerable]]:可枚举的,决定属性是否可被遍历
- [[configurable]]:可配置的,决定属性是否可删除和改变(改变数据的类型)
- enumerable和configurable默认值都为true,可遍历和可配置
Object.getOwnPropertyDescriptor(Object,property)可以查看对象中单个属性的特性
Object.getOwnPropertyDescriptors(Object)可以查看对象中所有属性的特性
var obj = {
fname: '张三',
get getName(){
return this.fname + '就是张三啊!';
},
set setName(name){
return this.fname = name;
}
}
var descriptor = Object.getOwnPropertyDescriptor(obj, 'fname');
console.log(descriptor); // {value: "张三", writable: true, enumerable: true, configurable: true}
var descriptors = Object.getOwnPropertyDescriptors(obj);
console.log(descriptors);
/*
fname: {value: "张三", writable: true, enumerable: true, configurable: true}
getName: {set: undefined, enumerable: true, configurable: true, get: ƒ}
setName: {get: undefined, enumerable: true, configurable: true, set: ƒ}
*/
(2)数据属性的特性
-
value:"张三":属性保存的数据
-
writable: true:决定属性是否可以写入数据
-
enumerable: true:决定数据是否可以被遍历
-
configurable: true:决定数据是否可以被删除和改变(类型的改变)
Object.defineProperty(obj, property, {})和Object.defineProperties(obj, {property:{}})两个方法可以修改属性的特性,如果对象中没有该属性会自动添加到对象中
var obj = {
fname: '张三',
lname: '李四'
}
// 修改属性的特性
Object.defineProperty(obj, 'fname', {
enumerable: false,
configurable: false,
writable: false
});
// 查看fname特性
var descriptor = Object.getOwnPropertyDescriptor(obj, 'fname');
console.log(descriptor); // {value: "张三", writable: false, enumerable: false, configurable: false}
// 遍历,遍历不出
for(var key in obj){
console.log(obj[key]); // 只打印出,李四
}
// 修改,无效
obj.fname = '尼古拉斯~赵四';
console.log(obj.fname); // 张三
// 删除,无效
delete obj.fname;
console.log(obj.fname); // 张三
Object.defineProperties(obj, {
'lname':{
enumerable: false,
},
'age': {
value: 18,
writable: false
}
})
console.log(obj); // {fname: "张三", lname: "李四", age: 18}
(3)访问器属性的特性
- configurable: true, 决定了属性是否可以被删除和改变(属性的类型)
- enumerable: true, 决定了属性是否可以被枚举(变量)
- get: ƒ fullName(), 访问属性时,调用该方法
- set: ƒ fullName(newFullName) 修改属性时,调用该方法
var obj = {
fname: '张三',
lname: '李四'
}
// 修改数据属性为访问器属性
obj.lname = function(){
return this.fname;
}
console.log(obj.lname());
六、禁止对象修改对象
对象的内部特性[[Extensible]]表示对象是否可以进行扩展,也就是说是否可以添加新的属性,默认情况下是可扩展的。
[[Extensible]]的值为false时,对象无法添加新属性。
有三种方法禁止对象扩展:
(1)禁止扩展:Object.preventExtensions()
检测是否可扩展: Object.isExtensible()
var obj = {
fname: '刘能',
}
// 查看对象是否可扩展
console.log(Object.isExtensible(obj)); // true
// 修改对象的特性
Object.preventExtensions(obj);
// 查看
console.log(Object.isExtensible(obj)); // true
obj.age = 40;
obj.gender = 'male';
console.log(obj); // {fname: "刘能"}
// 检测属性是否可以遍历
console.log(obj.propertyIsEnumerable('fname'));
// fname: {value: "刘能", writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptors(obj));
(2)封印对象:Object.seal()
检测对象是够被封印:Object.isSealed()
[[configurable]]=false,属性无法被删除和改变类型
var obj = {
fname: '刘能',
}
// 查看对象是否被封印
console.log(Object.isSealed(obj)); // false
// 封印对象
Object.seal(obj);
// 查看
console.log(Object.isSealed(obj)); // true
// 添加新属性
obj.age = 40;
obj.gender = 'male';
console.log(obj); // {fname: "刘能"}
// 检测属性是否可以遍历
console.log(obj.propertyIsEnumerable('fname'));
// fname: {value: "刘能", writable: true, enumerable: true, configurable: false}
console.log(Object.getOwnPropertyDescriptors(obj));
delete obj.fname;
console.log(obj); // {fname: "刘能"}
(3)冻结对象:Object.freeze()
检测对象是否被冻结:Object.isFrozen()
writable: false,configurable: false,属性不可以修改数据、删除和改变类型
var obj = {
fname: '刘能',
}
// 查看对象是否被冻结
console.log(Object.isFrozen(obj)); // false
// 冻结对象
Object.freeze(obj);
// 查看
console.log(Object.isFrozen(obj)); // true
// 添加新属性
obj.age = 40;
obj.gender = 'male';
console.log(obj); // {fname: "刘能"}
// 检测属性是否可以遍历
console.log(obj.propertyIsEnumerable('fname')); // true
// fname: {value: "刘能", writable: false, enumerable: true, configurable: false}
console.log(Object.getOwnPropertyDescriptors(obj));
delete obj.fname;
console.log(obj); // {fname: "刘能"}
obj.fname = '赵四';
console.log(obj.fname); // 刘能