js的面向对象概念跟C++、Java不太一样,更像是一个精简版的设计(可能是因为语言设计者本身讨厌面向对象随便为了应付弄出来一个?还是为了减轻浏览器的负担才这么设计,我觉的是第二者哦,毕竟解释型程序没有编译型程序效率高)。
ECMAScript对对象的定义:”无需属性的集合,其属性可以包含基本值、对象或者函数“。等等,这句话眼熟啊,想起来了吧,Object类型就是这么定义的啊。所以,Object类型就是js里所有对象(类)的父类。
而所有通过new Array、new String的变量都是Array类\String类的实例,当然Array、String类的父类也都是Object。
我们知道,做为一个对象,要有属性和方法,js里创建自定义对象的主流方法是字面量方法,如下:
<script>
//这实际是Object的一个实例
var Mouse = {
name : "老鼠",
sayHello : function () {
alert("吱吱吱");
}
}
Mouse.sayHello();
</script>
相当于:
var Mouse = new Object(); //创建Object的实例
Mouse.name = "老鼠";
Mouse.sayHello = function () {
alert("吱吱吱");
}
Mouse.sayHello();
但是这种字面型创建实例的方法,除了做为配置文件外其实我觉的没什么用,因为在创建实例的时候,我们一般需要传入参数进去,建立自己的类,并通过类创建实例更加有用,后续再介绍。Mouse对象有一个name属性和一个sayHello()方法,在js中,制造属性的方法有两种,一种是“赋值”、一种是“定义”。
“制造(或修改)"一个新(或者已经存在)的属性,赋值的方法就是我们上边代码内用的方法,定义的方法是通过Object.defineProperty()函数实现的,用法为Object.defineProperty(对象,属性名,配置文件);,后边我们会举例说明。
通过赋值和定义方法制造出来的属性会有不同,主要表现在:
- 定义方法:对象如果本身已经存在了这个属性,则修改,如果不存在则新定义。只针对本身对象操作。
- 赋值方法:如果对象本身存在这个属性,则修改,如果不存在,会根据原型链往上找,如果找不到,则在对象本身上进行属性制造,如果找到了,那就麻烦大了。。。。。(这篇博文看了都不用看我这个,我这个只是为了总结学习用。http://www.cnblogs.com/ziyunfei/archive/2012/10/31/2738728.html)
所以区别就是,定义方法制造属性只针对当前对象本身操作,而赋值会进行原型链查找。
在js里,属性的分类有三种:数据属性、访问器属性、内部属性,他们的区别如下:
- 数据属性:拥有确定值的属性。
- 访问器属性:配置了getter和setter的数据属性。
- 内部属性:javaScript引擎内部使用的属性,比如原型属性等。
也就是说,实际上name属性是还有属性的,它的属性是定义了它属性本身的一些特点。也就是说,数据属性和访问器属性是可以配置的,具体来说,他们两个各自有四个属性(其中有两个是共同的),也就是数据属性和访问器属性都各自有两个特性属性,还有两个公用属性:
共用属性:
- [[Configurable]]:能否通过delete删除从而重新定义属性。
- [[Enumerable]]:能否通过for-in循环返回属性。
数据属性特有属性:
- [[Writeable]]:能否修改属性的值。
- [[Value]]:包含这个属性的数据值。读取属性值的时候从这里读取,写入的时候写入到这里,默认为undefined。
访问器属性特有属性:
- [[Get]]: 存储着getter方法。
- [[Set]]: 存储着setter方法。
下面举例通过Object.defineProperty()方法设置属性如下(其他属性设置也是如此,但是可以一次性设置多个属性):
<script>
//这实际是Object的一个实例
var Mouse = {
name : "老鼠",
sayHello : function () {
alert("吱吱吱");
},
sayName : function () {
alert(this.name);
}
};
Object.defineProperty(Mouse,"name",{
writable:false, //设置Mouse实例的name属性不能修改值
value:"耗子" //但是此处还是可以的,需要{}里的运行完才起作用?这里不清楚
});
Mouse.name = "耗子1"; //并没有什么用
Mouse.sayName(); //耗子
</script>
这是数据属性定义的方法,我们定义了一个已经存在的属性,所以JS就直接重写了name属性,如果我们定义一个age属性,则会新增加一个age属性,大家理解一下。下面写一段访问器属性的get、set方法:
<script>
//这实际是Object的一个实例
var Mouse = {
name : "老鼠",
sayHello : function () {
alert("吱吱吱");
},
sayName : function () {
alert(this.name);
}
};
Object.defineProperty(Mouse,"age",{ //通过定义方法增加了一个新的访问器属性,名字为age,age的getter是get函数,setter是set函数
get : function () { //
alert("getter接口");
return this.name;
},
set : function (ages) { //赋值操作会通过set函数执行。
alert("setter接口");
if (ages>10) {
this.name = "大耗子";
}
else {
this.name = "小耗子";
}
}
});
Mouse.age = 123; //通过set函数对age进行赋值
alert(Mouse.age); //通过get函数进行读取 显示123
</script>
所以我认为,如果你给属性设置了get或者set函数,那么他就是访问器属性,如果不设置,就是数据属性。当然,定义访问器属性的时候是无法使用数据属性的value值的,这也是区别吧,主要在方式方法上的区别。
那么,如何取得一个属性的特性呢,在ECMAScript5里,有一个Object.getOwnPropertyDescriptor()方法,它有两个参数,属性所在的对象和属性名。
接上边继续编码:
var a = Object.getOwnPropertyDescriptor(Mouse,"age");
console.dir(a);
a = Object.getOwnPropertyDescriptor(Mouse,"name");
console.dir(a);
结果如下:
当然,还可以一次性设置多个属性,用Object.definePropertys(),具体用法google吧。顺便说一下,貌似对象(实例)的方法应该也是可以通过定义和赋值进行制造的!