JS对象之属性的类型
JavaScript中有三种不同类型的属性:
命名数据属性(named data properties)
命名访问器属性(named accessor properties)
内部属性(internal properties).
例如下面的对象字面量:
var flight = { airline: "Oceanic", number: 815, departure: { IATA: "SYD", time: "2004-09-22 14:55", city: "Sydney" }, arrival: { IATA: "LAX", time: "2004-09-23 10:42", city: "Los Angeles" } };
所有的属性都可以归到命名数据属性一类
还可以使用Object.defineProperty定义数据属性
var person = {}; Object.defineProperty(person, "name", { writable: false, value: "lyx" }); console.log(person.name);//lyx person.name = "lyx2"; console.log(person.name);//lyx
上面这段代码定义了一个数据属性name,使用writable和value这两个特征值来描述name属性的行为或特征,name属性的特征为不可写入,内容为lyx。
数据属性有四个描述其行为的特性:
Configurable:设置属性是否可配置,即能否更改(包括名值)或者删除(delect)它,能否修改属性特性等等
Enumerable:设置属性是否可以枚举,即能否通过for-in循环返回
Writable:是否可写
Value:就是属性值,对象在读取属性值时就是从这个位置读取的.
//定义了一个访问器属性value //控制属性读取的访问器函数称之为getter.控制属性写入的访问器函数称之为setter. var people = { name: "lyx", get value() { return "uuuuu"; }, set value(value) { console.log("==========") this.name = value; } }; console.log(people.name); //lyx console.log(people.value);//uuuuu //调用访问器属性value(getter) people.value = "12344"; //调用访问器属性value(setter) console.log(people.name); //12344
另一种方式使用Object.defineProperty方式
这种方式定义了一个访问器属性year,访问器属性year包含了一个getter函数和setter函数。getter函数返回_year的值,setter函数通过计算确定正确的版本。
var book = { _year: 2004,//表示只能通过对象方法访问该属性 edition: 1 }; Object.defineProperty(book, "year", { //year就是一个访问器属性(访问器属性是一对get和set) configurable: false, enumerable: false, get: function () { return this._year; }, set: function (newValue) { if (newValue > 2004) { this._year = newValue; this.edition += newValue - 2004; } } }); book.year = 2005; console.log(book.edition);//2
有一些属性仅仅是为规范所用的,称之为内部属性,因为它们无法通过JavaScript直接访问到,但是它们的确存在,并且影响着程序的表现.内部属性的名称比较特殊,它们都被两个中括号包围着.下面有两个例子:
内部属性[[Prototype]]指向了所属对象的原型.该属性的值可以通过Object.getPrototypeOf()函数读取到.该属性的值只能在创建一个新对象的时候通过Object.create()或者__proto__来设置.
内部属性[[Extensible]]决定了是否能给所属对象添加新的属性.该属性的值可以通过Object.isExtensible()读取到.还可以通过Object.preventExtensions()将该属性的值设置为false.一旦设置为false,就无法再设置回true了.
一个属性的所有状态,包括它的数据和元数据,都存储在该属性的特性(attributes)中.属性拥有自己的特性,就像对象拥有自己的属性一样.特性的名称经常写成类似内部属性的形式(双中括号).
下面是命名数据属性拥有的特性:
[[Value]] 存储着属性的值,也就是属性的数据.
[[Writable]] 存储着一个布尔值,表明该属性的值是否可以改变.
下面是命名访问器属性拥有的特性:
[[Get]] 存储着getter,也就是在读取这个属性时调用的函数.该函数返回的值也就是这个属性的值.
[[Set]] 存储着setter,也就是在为这个属性赋值时调用的函数.该函数在调用时会被传入一个参数,参数的值为所赋的那个新值.
下面是两种类型的属性都有的特性:
[[Enumerable]] 存储着一个布尔值.可以让一个属性不能被枚举,在某些操作下隐藏掉自己(下面会有详细讲解).
[[Configurable]] 存储着一个布尔值.如果为false,则你不能删除这个属性,不能改变这个属性的大部分特性(除了[[Value]]),不能将一个数据属性重定义成访问器属性,或者反之.换句话说就是:[[Configurable]]控制了一个属性的元数据的可写性.
默认值
如果你不明确的指定某个特性的值,则它们会被赋一个默认值:
特性名称 默认值
[[Value]] undefined
[[Get]] undefined
[[Set]] undefined
[[Writable]] false
[[Enumerable]] false
[[Configurable]] false
var person = {}; Object.defineProperties(person, { personName: { configurable: false, writable: false, value: "nihao" }, _sex: { configurable: false, enumerable: false, writable: false, value: "male" }, sex: { get: function () { return this._sex; }, set: function (value) { this._sex = value; } } }); console.log(person.sex); //male
====END====