JavaScript面向对象(二)
我们上午创建的对象,可以看作是一个最基础的对象,那么我们再来看一些比较高级的对象,比如有一些特殊要求的属性,比如年龄应该是随着时间的增长而增长类似这类的属性我们要怎么定义
首先我们先看下面的对象
var person = {
name:"小芳",
sex:"女",
age:18,
height:165,
weight:60
}
首先我们创建了一个对象,分别给了5个属性,但是现在这个女生跟我说我的体重和身高保密,不能让别人知道,性别为女,不能被改变,怎么办?
如果我们想把已经创建好的对象的属性删除调,我们可以使用 delete
delete person.height;
delete person.weight;
使用delete删除对象的属性的时候,如果成功返回true,如果失败返回false
根据上面的琴科给我们知道delete这个关键字,在默认的情况下是可以删除调对象的所有的属性的,这种情况其实非常,怎么样在定义对象的时候不让别人能够删除调属性,或者是不让更改属性的值
Object.defineProperty() 定义对象属性
1、数据属性
通过这方式,我们可以定义一些特殊的对象属性
var stu1 = {}; //空对象
Object.defineProperty(stu1,"name",{
//关于特殊属性的定义
})
现在我们在对象stu1当中定义了一个属性 name
,现在它还是一个普通的属性,现在我们来看下,可以设置的特殊描述有哪些
数据属性:
数据属性是包含了一个数值的位置,可以在这个位置写入或者读取值,有4个描述具体行为的特征
Configurable: 表示能否通过delete删除这个属性从而从新定义属性,或者能否把属性修改成访问器属性,它的默认值是true
**Enumerable:**表示能否通过for…in循环遍历返回属性,这个的默认值是false
**Writable:**表示能否修改属性的值,它的默认值是true
Value: 包含这个属性的数据值,读取属性的时候,从这个位置读/写属性值的时候,把新值保存在这个位置,这个特性的默认值是undefined
var stu1 = {
aaa:"hello"
}
//我们开始添加一个特殊的数据属性
Object.defineProperty(stu1,"name",{
configurable:false, //false不能被delete关键字删除
enumerable:false, //不能被for in遍历出来
writable:false,
value:"小芳"
})
for(var i in stu1){
console.log(i);
}
console.log(stu1.name);
访问器属性
Configurable: 表示能否通过delete删除这个属性从而从新定义属性,或者能否把属性修改成访问器属性,它的默认值是true
**Enumerable:**表示能否通过for…in循环遍历返回属性,这个的默认值是false
**Get:**在读取属性的时候调用的函数,默认值是undefined
Set: 在写入属性的时候调用的函数,默认值是undefined
访问器属性不能直接被定义,必须使用Object.defineProperty() 来定义
//定义一个普通对象
var stu1 = {
birthDay:"1997-7-5"
};
//现在又一个学生对象,我们在这个对象里面先添加一个普通数据属性birthDay生日
//现在我们希望再给这个对象添加一个age属性,但是这个age属性的值要根据生日自动计算
Object.defineProperty(stu1,"age",{
configurable:false, //false不能被delete关键字删除
enumerable:true, //不能被for in遍历出来
get:function(){
return "你正在读取age这个属性";
},
set:function(v){
//这里的v就代表你要赋的值
console.log("你再对age这个属性赋值,你要赋的值是" + v);
}
})
console.log(stu1.age);
上面的get和set定义的age属性就是一个访问器属性,它在取值与赋值的时候分别调用了get和set的方法
接着我们就来看访问器属性的具体作用:
//定义一个普通对象
var stu1 = {
birthDay:"1997-7-5",
IDCard:"420502199904011066"
};
//现在又一个学生对象,我们在这个对象里面先添加一个普通数据属性birthDay生日
//现在我们希望再给这个对象添加一个age属性,但是这个age属性的值要根据生日自动计算
Object.defineProperty(stu1,"age",{
configurable:false, //false不能被delete关键字删除
enumerable:true, //不能被for in遍历出来
get:function(){
var currentDate = new Date(); //获得一个日期对象
var birthdayDate = new Date(this.birthDay) //生日的日期对象
//日期相减有一套专门的格式,这里先不纠结,后面专门来讲
//getTime方法是获取当前时间的毫秒数,1秒等于1000毫秒
var totalTime = currentDate.getTime() - birthdayDate.getTime();
var yearCount = parseInt(totalTime / 1000 / 60 / 60 /24 /365);
return yearCount;
},
//因为我们只有get方法,没有设置set方法,所以age这个属性只可以取值,但是不能赋值了
})
Object.defineProperty(stu1,"sex",{
get:function(){
//性别是根据身份证号的17位来决定的
if(this.IDCard[16] % 2 == 0){
return "女";
}else{
return "男";
}
}
})
console.log(stu1.age);
console.log(stu1.sex);
通过上面的访问器属性,我们设置了age和sex连个属性,age根据出生年月日来计算,sex则根据身份证号来决定的
所以我们通过上面的案例,得到访问器属性的有点
1、get方法主要针对取值的时候进行属性取值的控制,set方法针对赋值的时候对赋值操作进行控制
2、在上面的案例种我们没有写set方法,所有这个属性只能读取不能赋值
在上面的例子我们分别写了两次Object.defineProperty() 从而设置了age和sex两个属性,那么如果我们要同时设置多个属性的话怎么办?
Object.defineProperties()定义对象属性
它是 Object.defineProperty()
的复数形式,现在将上面两个属性合并定义一下
//定义一个普通对象
var stu1 = {
birthDay:"1997-7-5",
IDCard:"420502199904011066",
//我们现在要定义name属性不可以更改,不能删除
//age属性根据生日来
//sex属性根据身份证号来
};
Object.defineProperties(stu1,{
name:{
value:"zhangsan",
configurable:false,
writable:false
},
age:{
get:function(){
var currentDate = new Date(); //获得一个日期对象
var birthdayDate = new Date(this.birthDay) //生日的日期对象
//日期相减有一套专门的格式,这里先不纠结,后面专门来讲
//getTime方法是获取当前时间的毫秒数,1秒等于1000毫秒
var totalTime = currentDate.getTime() - birthdayDate.getTime();
var yearCount = parseInt(totalTime / 1000 / 60 / 60 /24 /365);
return yearCount;
}
},
sex:{
get:function(){
return this.IDCard[16] % 2 == 0 ? "女" : "男";
}
}
})
上面两种方式都是定义对象的特殊属性的,在定义特殊属性的时候,我们可以使用数据属性和访问器属性
获取对象属性的描述信息
下面有一段代码
var stu1 = {
//带上就是上面的stu1里面的代码,这里省略调
}
//得到name属性的描述信息
var nameDesc = Object.getOwnPropertyDescriptor(stu1,"name");
/*
configurable: false
enumerable: false
value: "zhangsan"
writable: false
*/
构造函数与特殊属性结合
构造函数与特殊属性的结合,主要指的就是构造函数与 Object.defineProperties()
的结合
案例:
现在要定义个构造函数 Person
,这个构造函数的创建的对象有5个属性,分别是 name,birthday,sex,age,IDCard
这5个属性不能被 delete,同时都是只读的, age属性是根据生日计算的,sex属性是根据身份证号决定的
function Person(_name,_birthday,_IDCard){
Object.defineProperties(this,{
name:{
value:_name,
configurable:false,
writable:false
},
birthday:{
value:_birthday,
configurable:false,
writable:false
},
IDCard:{
value:_IDCard,
configurable:false,
writable:false
},
age:{
configurable:false,
get:function(){
var currentDate = new Date(); //获得一个日期对象
var birthdayDate = new Date(this.birthday) //生日的日期对象
//日期相减有一套专门的格式,这里先不纠结,后面专门来讲
//getTime方法是获取当前时间的毫秒数,1秒等于1000毫秒
var totalTime = currentDate.getTime() - birthdayDate.getTime();
var yearCount = parseInt(totalTime / 1000 / 60 / 60 /24 /365);
return yearCount;
}
},
sex:{
configurable:false,
get:function(){
return this.IDCard[16] % 2 == 0 ? "女" : "男";
}
}
})
}
var person1 = new Person("张三","2010-5-1","420502201005010035");
delete person1.name; //false
console.log(person1.age);