JS对象之属性的类型

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直接访问到,但是它们的确存在,并且影响着程序的表现.内部属性的名称比较特殊,它们都被两个中括号包围着.下面有两个例子:

  1. 内部属性[[Prototype]]指向了所属对象的原型.该属性的值可以通过Object.getPrototypeOf()函数读取到.该属性的值只能在创建一个新对象的时候通过Object.create()或者__proto__来设置.

  2. 内部属性[[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====


你可能感兴趣的:(JS对象之属性的类型)