对象函数
ECMA-262把对象定义为:“无序属性的集合,其属性能够包含基本值、对象或者函数。”性能
因而,咱们能够将对象想象成散列表:就是一些名值对,其中值能够是数据或函数this
1.理解对象及其内部机制spa
咱们先来建立一个最简单的Object实例,同时为它添加属性和方法:code
1 var person=new Object();
2 person.name="Sleipnir"; 3 person.age=23; 4 person.job="Software Enginner"; 5 6 person.sayname=function(){ 7 alert(this.name); 8 };
有时候这种直接赋值的方式太繁琐,咱们还能够用对象字面量的方式来赋值:对象
1 var person={
2 name:"Sleipnir", 3 age:23, 4 job:"Software Enginner", 5 6 sayname:function(){ 7 alert(this.name); 8 } 9 };
这两种建立对象的效果都是同样的,下面,咱们来深刻对象内部,来探讨属性类型blog
2.属性类型ip
ECMAScript有两种属性:数据属性 和 访问器属性get
2.1数据属性:它包含一个数据值的位置,在这个位置能够读取和写入值,它有4个用来描述其行为的特性:Configurable\Enumerable\Writable\Valueit
Configurable:表示可否经过delete来删除从而从新定义属性,它的默认值为true;
Enumerable:表示属性可否被使用for-in来遍历,默认值为true;
Writable:表示可否被修改,默认值为true;
Value:包含属性的数据值,默认值为underfined
像在上面对象中直接定义的属性,它们的configurable,enumerable,writable都默认是true,value就是设置的“Sleipnir”这个值
想查看特性的值,就须要用到Object.getOwnPropertyDescriptor()这个方法:
在上面的对象的基础上,咱们来查看属性的特性:
1 var aa=Object.getOwnPropertyDescriptor(person,"name"); 2 console.log(aa.configurable); //true 3 console.log(aa.enumerable); //true 4 console.log(aa.writable); //true 5 console.log(aa.value); //"Sleipnir"
要想修改默认的特性,就要用到Object.defineProperty()这个方法,概念不说太多,咱们直接来举个栗子:
在上面的对象的基础上,咱们来修改属性的特性:
1 Object.defineProperty(person,"name",{ 2 writable:false, 3 enumerable:false, 4 value:"xiaoxiao", 5 configurable:false 6 }); 7 8 console.log(person.name); //"xiaoxiao" 9 person.name="love"; 10 console.log(person.name); //"xiaoxiao"
从上面的代码能够看出,当writable从默认的true被修改为false后,你再给name赋值就没法成功了,它仍是显示默认的“xiaoxiao”
然而,有一点要注意,当把confugurable设置成false后,就没办法把属性设置回可设置状态了,换句话说,是不可逆的,当把confugurable设成false后,再用 Object.defineProperty()修改除writable以外的特性,都会致使错误
这里有个坑,你直接在对象上定义的属性,它的数据属性值都默认是true,可是若是你是用Object.defineProperty()给对象建立的属性,configurable、enumerable和writable特性的默认值都是false
固然了,一个一个属性修改太麻烦了,因而还有个Object.defineProperties(),能同时修改多个属性:
1 Object.defineProperties(person,{ 2 name: { 3 writable:true, 4 value:"long" 5 }, 6 age: { 7 writable:true, 8 value:25 9 }, 10 job: { 11 writable:true, 12 value:"gongren" 13 } 14 }); 15
2.2 访问器属性:跟数据属性同样,它也有4个特性:configurable,enumerable,get,set
前两个特性不用赘述,后两个get和set分别是读取/写入属性时调用的函数,默认值都是underfined
访问器属性无法直接定义,必须使用Object.defineProperty()来定义,举个栗子:
1 var book={ _year:2017, 2 edition:1 3 }; 4 Object.defineProperty(book,"year",{ 5 get: function(){ 6 return this._year; 7 }, 8 set: function(newValue){ 9 if(newValue>2017){ 10 this._year=newValue; 11 this.edition+=newValue-2017; 12 } 13 } 14 }); 15 16 book.year=2018; 17 console.log(book.edition); //2
这里就是比较有意思的地方,咱们加入的属性“year”,在加入时并无赋值,而是定义了get和set函数,用来处理在外部赋给year的值,咱们在外面赋值2018,而后给year定义的get和set函数就利用2018来修改_year和edition的值。这就是使用访问器属性的常见方式,即设置一个属性的值会致使其余属性发生变化
看到这里,可能有的同窗有个问题:不是说用Object.defineProperty()方法定义的属性的特征值包括writable都是false吗?为何“book.year=2018”还能生效呢?
其实缘由是,你用Object.getOwnPropertyDescriptor()取得特征值查看会发现,它的writable显示为“underfined”,因此能够这样想,year并非和_year,edition同样的属性,是个定义了用来修改其余属性的属性,地位至关于后勤部长。