理解对象
任何事物都可以看作对象,对象就是五级无序名/值对的集合。对象有属性和方法。对象就是 无序属性 的集合,属性可包括基本值、对象和函数,简单地说就是一组无特定顺序的值,由名/值对组成,值可以是数据或函数。属性名是字符串,我们也将对象看成是从字符串到值的映射,当然,对象除了本身的属性外,还可以从一个叫原型的对象继承属性。
在JavaScript中,除了字符串、数字、true、false、null和undefined外,其它的值均是对象。
对象可以由关键字new后跟构造函数Object()创建:
var obj = new Object();
obj.name = "Tom";
obj.age = 20;
obj.job = "javaScript";
obj.sayName = function () {
alert(this.name);
};
对象也可以由字面量法创建:(常用的方法)
var obj = {
name : "Tom",
age : 20,
job : "javaScript",
sayName : function() {
alert(this.name);
}
};
属性类型
在定义只有在内部才用的特性(attribute)时,描述了属性(property)的特性,特性是内部值,将其放于两对方括号中,即[writable]。
JavaScript中有两种属性:数据属性和访问器属性。
数据属性
数据属性包含一个数据值的位置,这个位置可以读取和写入值。数据属性有value特性,无get、set特性。
数据属性的特性:
1、[[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,能否把属性修改成访问器属性。默认为true。
2、[[Enumerable]]:表示能否通过for-in遍历并返回属性。默认为true。
3、[[Writable]]:表示能否修改属性。默认为true。
4、[[Value]]:包含这个属性的数据值。读取属性值时,从这个位置读取,写入属性值,把值保存在这个位置。
var person = {
name : "Tom"
};
这里为对象person创建了一个名为name的属性,给定值是"Tom",也就是说[[Value]]被设置成"Tom",要修改属性的默认特性,需用Object.defineProperty()方法。这个方法接收三个参数:属性所在的对象、要修改或新创建的属性名和一个描述符对象,描述符对象必须是:configurable、enumerable、writable、value。设置其中一个或多个,可以修改对应的特性。注:属性名需用引号括起来。
var person = {};
Object.defineProperty(person, "name", {
writable : false,
value : "Tom"
});
console.log(person.name); //Tom
person.name = "Bob";
console.log(person.name); //Tom
同样也可以这样做:
var person = {};
Object.defineProperty(person, "name", {
configurable : false; //不可通过delete删除属性并重新定义属性
value : "Tom"
});
console.log(person.name); //Tom
delete person.name; //删除属性操作
console.log(person.name); //Tom
为对象person创建了一个属性name,并规定其不能通过delete删除,所以最后person.name还在。
注:当规定对象的属性不能通过delete删除后,如果再次规定其属性能删除,则会抛出错误。
var person = {};
Object.defineProperty(person, name, {
configurable : false; //先规定不能 通过delete删除属性并重新定义属性
value : "Tom"
});
//抛出错误
Object.defineProperty(person, "name", {
configurable : true; // 再次规定可以删除属性,这时会报错
value : "Tom"
});
如果先规定对象的属性能删除,再次规定不能删除就不会出错。
以上可以总结为:
var person = {name : "jon", age : 21}; //初始化对象
Object.defineProperty(person, "name", {
writable: false, //当设置数据为不能修改时
configurable: true,//设置能通过delete删除属性特性
value : "Tom" //将name的值设置为Tom
});
console.log(person.name);//通过修改特性,name的值已经被修改为Tom
//修改name的值
person.name = "Bob";
//输出还是为Tom,因为不能修改name的值
console.log(person.name);
//删除name属性的操作
delete person.name;
//undefined,已经删除name属性
console.log(person.name);
当使用Object.defineProperty()方法创建新的属性时,如果先不指定属性特性,在默认情况下,configurable、enumerabel、writable均为false。
Object.defineProperty()不仅可以修改属性的特性,还可以用于定义新的属性。
var person = {name : "jon", age : 21};
Object.defineProperty(person, "name", {
writable: false,
configurable: false,
value : "Tom"
});
Object.defineProperty(person, "name", {
writable: true,
configurable: true,
value : "Tom"
});
以上代码会出错。
注:多次修改除writrable以外的特性,如果第一次设置为false,那么之后如果再次设置为true,则会报错。也就是说,第一次设置为false后,再交修改为true,是不允许的,会出错的。
访问器属性
访问器属性不包含数据值,即value为undefined 。包含get()和set()方法。当读取访问属性时,会调用getter函数,当写入访问属性时,会调用setter函数。访问器属性也有四个特性:
1、[[configurable]]:能否通过delete删除属性并重新定义属性,能否修改属性,能否将属性变成数据属性。
2.[[enumerable]]:能否通过for-in遍历并返回属性。
3、[[get]]:读取属性时调用该函数。默认为undefined
4、[[set]]:写入属性时调用该函数。默认为undefined
访问器属性不能直接定义,必须通过Object.defineProerty()来定义。
var value = {
_year : 2017,
edition : 1
};
Object.defineProperty(value, "year",{
get : function() { //读取并返回year属性的值
return value.year;
},
set : function (newValue) {
if (newValue > this.year) {
this.year = newValue; //将新值赋值于year
this.edition += newValue - 2017;
}
}
});
value.year = 2018;
console.log(this.edition); //2
使用访问器属性常见方式,即改变一个属性year的值,另一个属性值_year也相应变改变。
setter和getter不一定要同时定义,当只定义getter时,只能读取属性,此时设置setter会抛出错误。同理,当只定义seter时,只能写入属性,此时再设置getter会抛出错误。
定义多个属性
可以通过Object.defineProperties()来创建多个属性。该方法接收两个 对象参数,第一个对象是 要添加和修改属性的对象,第二个对象的属性 与 第一个对象中要添加和修改的属性 一一对应。
var value = {}; //定义一个对象
Object.defineProperties(value, {
//为对象value添加两个属性year、edition
_year : {
writable : true,
value : 2017
},
edition : {
writable : true,
value : 1
},
//创建访问器属性
year : {
get : function () {
return this.year;
},
set : function (newValue){
if (newValue > this._year) {
this.year = newValue;
this.edition +=newValue - 2017;
}
}
}
});
value._year = 2018;
console.log(value.edition); 2
以上对象与前两个例子中的对象一样,只能此例子的两种属性是同时创建的。
读取属性的特性
使用Object.getOwnPropertyDescript()可以读取给定属性的描述符。该方法有两个参数:属性所在 对象和要读取其描述符的 属性名称。
如果是数据属性,这个对象的属性有:configurabel、enumerable、writable、value。
如果是访问器属性,这个对象的属性有:configurable、enumerable、writable、value。
var value = {};
Object.defineProperties(value, {
//创建数据属性
_year : {
value : 2017
},
edition : {
value : 1
}
//创建访问器属性
year : {
get : function() {
return this.year;
},
set : function(newValue) {
if (newValue > 2017) {
this.year = newValue;
this.edition += newValue - 2017;
}
}
}
});
//读取数据属性的特性
var descriptor = Object.getOwnPropertyDescriptor(value, "_year");
console.log(descriptor.value); //2017
console.log(descriptor.configurable); //false 默认为false 因为这个属性是通过defineProperties()新创建的。
console.log(descriptor.get); //undefined,数据属性没有get函数
//读取访问器属性的特性
var desciptor = Object.getOwnPropertyDescriptor(value, "year");
console.log(descriptor.value); //undefiend 访问器属性没有数据值
console.log(descriptor.configurable); //false 默认为false 因为这个属性是通过defineProperties()新创建的。
console.log(descriptor.get); //function
对于数据属性没有getter函数的指针。对于访问器属性没有数据值即value为undefined。configurable特性默认情况均是false。