面向对象语言的的特性就是有类(class)的概念,通过类可以创建任意多个具有相同属性或方法的对象,然而 javascript 中没有类(class)的概念,所以它不是真正的面向对象
对象
由N组键值对组合起来的无序属性顺序的结合,其属性值可以是任意类型。
//采用生成一个 Object 的实例来创建一个对象
var obj = new Object();
obj.name = "大毛";
obj.eat = function(){
console.log("吃鱼")
}
//采用字面量方式创建新对象
var obj = {
name: "大毛",
eat: function(){
console.log("吃鱼")
}
}
以上我我们利用 Object 的构造函数和字面量方式创建了单个对象,但,这种模式创建出来的对象有个明显的缺陷:
同一个接口创建多个对象,会有很多重复代码,那如何解决呢?带着这个问题,我们继续探究…
属性类型
数据属性
修改获取属性值时
- [[Configurable]] :是否能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,能够把属性改为访问器属性。能够直接在对象上定义的属性,默认值是true。
- [[Enumerable]] : 能否通过 for-in 循环返回属性。能够直接在对象上定义的属性,默认值是true。
- [[Writable]] : 能否修改属性的值,能够直接在对象上定义的属性,默认值是true。
- [[Value]] :属性的值,读取属性时,从这里读,写入的时候把新值保存在这里,默认是Undefined。
修改属性的默认特性,需要使用 Object.defineProperty() ,接受三个参数,属性所在对象、属性名称、描述符对象。描述符对象的属性必须是configurable、enumerable、writable、value
。设置其中的一个或多个值。
Object.defineProperty() 是 IE8 最先实现的,但这个版本只能在DOM对象上使用,而且只能创建访问器属性,由于实现的不彻底,不建议在 IE8 使用。
var person = {}
Object.defineProperty(person,"name",{
writeable:false, //不能修改属性值,严格模式下会报错,非严格忽略修改的值
configurable:false,//不能删除该属性
value:"Nic"
})
alert(person.name) //Nic
person.name = "Gre";
alert(person.name); //Nic
delete person.name;//返回false,不能够删除属性
alert(person.name); //Nic
访问器属性
访问器属性不包含数据值,他们包含一对 getter 和 setter 函数(但这2个函数不是必须),在读取访问器属性时,会调用 getter 函数,这个函数负责返回有效的值,在写入访问器属性时,会调用 setter 函数并传入新值,这个函数负责如何处理新值。
访问器属性具体 4 个特性:
- [[Configurable]] :能否通过 detele 删除属性从而重新定义属性,能否修改属性的特性,能否把属性修改为数据属性,
对于直接在对象上定义的属性,默认值是 true
。 - [[Enumerable]] :能否通过 for-in 循环返回属性列表,
对于直接在对象上定义的属性,默认值是 true
。 - [[Get]] :在读取属性时调用的函数,默认值是 Undefined。
- [[Set]] :在写入属性时调用的函数,默认值是 Undefined。
访问器属性不能直接定义,只能用 Object.defineProperty() 来定义。
var book = {
_year:2004,
edition:1
}
Oject.defineProperty(book,"year",{
get:function(){
return this._year;
}
set:function(){
if(newValue > 2004){
this._year = newValue;
this.edition += newValue - 2004;
}
}
})
book.year = 2005;
alert(book.edition); //2
_year 前面的下划线是一种常用的记号,表示只能通过对象方法访问的属性。而访问器属性 year 包含一个 getter 和 setter 函数。getter 函数返回 _year 属性的值,setter 函数则通过计算来确定正确的版本。因此 this.edition 会变成2,这是使用访问器属性的常见方式,设置一个属性的值会导致其他属性发生变化。
不一定非要同时指定这2个函数,只指定 getter 意味属性不能写,严格模式下写入会报错,非严格下忽略。只指定了 setter 函数属性不能读,严格模式下会报错,非严格下返回Undefined。
在不支持 Object.defineProperty() 方法的浏览器中不能修改 [[Configurable]] 和 [[Enumerable]]。
Object.defineProperies() 可以通过描述符一次定义多个属性。接受2个参数,一个对象的要添加的和修改的属性的对象。第二个是对象的属性与第一个对象中添加和修改的属性一一对应
这样定义的属性都是同一时间创建的。
var book = {}
Object.defineProperies(book,{
_year:{
value:2004
}
edition:{
value:1
}
year:{
get:function(){
return this._year;
}
set:function(){
if(newValue > 2004){
this._year = newValue;
this.edition += newValue - 2004;
}
}
}
})
读取属性特性
Object.getOwnPropertyDescriptor() 方法,可以取得属性的描述。接受2个参数,属性所在对象和读取描述符的属性名称。返回值是一个对象。
如果是访问器属性,这个对象的属性有,configurable、enumerable、get 和 set。
如果是数据属性,这个对象的属性有,confiurable、enmuerable、writable 和 value。
var obj = {}
obj.name = 22;
Object.getOwnPropertyDescriptor(obj,"name")
// {value: 22, writable: true, enumerable: true, configurable: true}