理解对象(一):属性类型及其特性

来源:互联网 发布:淘宝上大胸内衣 编辑:程序博客网 时间:2024/05/22 14:14

属性类型

ECMAScript有两种属性:

1.数据属性:

数据属性包含一个数据的位置,在这个位置可以读取和写入值。

2.访问器属性

访问器属性不包含数据值:它们包含一对getter和setter函数(不过这两个函数都不是必须的),在读取访问器属性时,会调用getter函数,这个函数负责返回有效的值;在写入访问器属性时,会调用setter函数并传入新值,这个函数负责决定如何处理数据。
对象属性是由名字,值和一组特性(attribute)构成的。
在介绍对象属性的特性之前先介绍两个属性:

getter和setter

在ECMAScript5中,属性值可以用一个或两个方法代替,这两个方法就是getter和setter。由这两个函数定义的属性称为“存取器属性”,它不同于“数据属性”,数据数据属性只有一个简单的值。程序在查询存取器属性的值的时候,JS调用getter方法(无参数)。这个方法的返回值就是属性存取表达式的值。当程序设置一个存取器属性的值,JS调用setter方法,将赋值表达式右侧的值当做参数传入setter。这个方法负责设置属性值。可以忽略setter方法的返回值。
和数据属性不同,存取器属性不具有可写性。如果一个数据同时具有getter和setter方法,那么它是一个读/写属性。如果它只有getter方法,那么它是一个只读属性,如果它只有setter方法,那么它是一个只写属性,读取只写属性总是返回undefined。
实例1:

    var p = {             x:1.0,//用对象字面量定义对象的属性             y:1.0,             //r是可读可写属性,它包含有getter和setter方法             get r(){return Math.sqrt(this.x*this.x+this.y*this.y);},//getter和setter也是属性             set r(newvalue){                var oldvalue = Math.sqrt(this.x*this.x+this.y*this.y);                var ratio = newvalue/oldvalue;                this.x *= ratio;                this.y *= ratio;//用于设置属性             },             //theta是只读存取器属性,它只有getter方法             get theta(){return Math.atan2(this.y,this.x);}        };        console.log(p);

实例2:

var random = {            get octet(){return Math.floor(Math.random()*256);},            get uint16(){return Math.floor(Math.random()*65536);}        };

存取器属性定义为属性,这个函数定义没有使用function关键字,而是使用get和set。
和数据属性一样,存取器属性是可以继承的

属性特性

1.介绍属性特征

除了包含名字和值之外,属性还包含一些标识它们科协,可枚举和可配置的特性。在ECMAScript3无法设置这些特性,所有通过ECMAScript设置的属性都是可写的,可枚举的和可配置的,且无法对这些特性做出修改。在这里,我们将存取器属性的getter和setter方法堪称为属性的特性。依照这个逻辑,我们也可以把数据属性的值同样看做属性特性,
因此可以认为一个属性包含名字和四个特性。
数据属性的四个特性分别是它的值(value),可写性(writable),可枚举性(enumerable)和配置性(configurable)。存取器属性不具有值(value)特性和可写性,它们的可写性是由setter方法存在与否决定的。因此存取器属性的4个特性是读取(get),写入(set),可枚举和可配置。

2.获取某个对象特定属性的属性描述符:Object.getOwnPropertyDescriptor()

举例:

  function Person(){            this.name = "Bob",            this.color = "white",            this.sayhi = function(){                alert("hello");            }        }        Person.prototype.height = "100px";        var person1 = new Person();        var spec = Object.getOwnPropertyDescriptor(person1,"name");        var spec1 = Object.getOwnPropertyDescriptor(person1,"height");        var spec2 = Object.getOwnPropertyDescriptor(Person,"height");        //输出{value:"Bob",writable:true,enumerable:true,configurable:true}        console.log(spec);        //输出undefined        console.log(spec1);        //输出undefined        console.log(spec2);

Object.getOwnPropertyDescriptor()只能得到自有属性的描述符。要向获得继承属性的特性,需要遍历原型链。

设置属性特性或者想让新建属性具有某种特性值:Object.definePeoperty()

传入要修改的对象,要创建或修改的属性的名称以及属性描述符对象
先解释一下属性描述符对象:ECMAScript定义的一个对象。这个对象代表那四个特性。描述符对象的属性和它们所描述的属性特性是同名的。因此,数据属性的描述符对象的属性有value,writable,enumerable和configurable。存取器属性的描述符对象则用get属性和set属性代替value和writable。
举例:

var o = {};//创一个新的空对象        //添加一个不可枚举的数据属性,并且赋值为1        Object.defineProperty(o,"x",{value:1,writable:true,enumerable:false,configurable:true});        //属性是存在的,但是不可枚举        console.log(o.x);//1        console.log(Object.keys(o));//输出[]        //现在对属性x做修改,让它变为只读        Object.defineProperty(o,"x",{writable:false});        o.x = 2;        console.log(o.x);//1        //属性依然是可配置的,因此可以通过下面这种方法来对它进行修改        Object.defineProperty(o,"x",{value:2});        console.log(o.x); //2        //现在将x从数据属性修改为存取器属性        Object.defineProperty(o,"x",{get:function(){return 0;}})        console.log(o.x);//0

传入Object.defineProperty()的属性描述对象不必包含所有4个特性。对于新创建的属性来说,默认的特性值是false或undefined。对于修改的已有属性来说,默认的特性值做任何修改。
注意:这个方法要么修改已有属性要么创建自有属性,但是不能修改继承属性。

如果要同时创建多个属性,则需要使用Object.definneProperties(),第一个参数是要修改的对象,第二个参数是一个映射表,它包含要创建或修改的属性的名称,以及它们的属性描述符。重点内容

小插曲:属性访问表达式

属性访问表达式运算得到一个对象属性或一个数组元素的值。JS为属性访问定义了两种语法:

//expression指定对象,identifer指定需要访问的属性名称expression.identifer//expression指定对象,第二个表达式指定要访问的属性的名称或者代表要访问数组元素的索引expression[expression]

不管用哪种形式的属性访问表达式,在.或者’[‘的表达式总是会首先计算。如果计算结果是null或者undefined,表达式会抛出一个类型错误异常,因为这两个值都不能包含任意属性的值

如果运算结果不是对象(或者数组),JS会将其转换为对象

用.indentifer的写法=更加简单,但是需要注意的是这种方式只适用于访问的属性名称是合法的标识符,并且需要知道要访问的属性名称。如果属性名称是一个保留字或者包含空格标点符号,或者是一个数字(对于数组),则必须使用方括号的写法。

阅读全文
0 0
原创粉丝点击