面向对象--内部属性类型

js中的对象有一些内部才用的特性,这些特性是为了实现javascript引擎用的,因此在javascript中不能直接访问它们。

有两种属性:数据属性 && 访问器属性

数据属性
  • [[ configurable ]]: 表示能否通过 delete 删除属性然后重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。直接在对象上定义的属性,它们这个特性的默认值为 true;
  • [[ enumerable ]]: 表示能否通过 for-in 循环返回属性。直接在对象上定义的属性,它们这个特性的默认值为 true;
  • [[ writable ]]: 表示能否修改属性的值。直接在对象上定义的属性,它们这个特性的默认值为 true;
  • [[ value ]]: 包含这个属性的数据值。读取属性值的时候,从这个位置读;写入属性的时候,把新值保存在这个位置。这个特性的默认值为 undefined ;

要修改属性的特性,必须使用 ES5 的 Object.definePrototype() 方法。这个方法接受三个参数:

1、属性所在的对象。

2、属性的名字。

3、描述符对象。属性必须是:configurableenumerablewritablevalue中的一个或多个。

var obj = {};
Object.defineProperty(obj, 'name', {
    writable: false,  // 不能修改值
    value: '张三'
})
console.log(obj.name); // 张三
obj.name = '李四';
console.log(obj.name); // 张三,  writable设为 false 后,值就没法修改了。
var person = {
    name: '李四',
    age: 24
}
delete person.name;
console.log(person); // {age: 24}
Object.defineProperty(person, 'age', {
    configurable: false
})
delete person.age; 
console.log(person);// {age: 24} configurable特性设为 false 后,就没法使用 delete 删除了。
复制代码

把 configurable 设置为 false 后,就不能用 delete 删除属性,而且,也不能修改 除 writable 外的特性。

var obj = {};
Object.defineProperty(obj, "name", {
    configurable: false,
    value: '张三'
})

// 会抛出错误
Object.defineProperty(obj, "name", {
    configurable: true,
    value: '张三'
})
复制代码

也就是说,可以多次调用 Object.defineProperty()方法修改同一个属性,但在把 configurable特性设置为 false 后就有限制了。

在调用Object.defineProperty()方法创建一个新的属性时,如果不指定,configurableenumerablewritable 特性的默认值都是 false,如果是修改已存在的属性,就不会有这个限制。

访问器属性

访问器属性没有数据值,有getset函数。读取访问器属性时,会调用 get函数,在写入值时会调用set函数。

访问器属性有如下四个特性:

  • [[ configurable ]]: 表示能否通过 delete 删除属性,从而重新定义属性。能否修改属性的特性,或者能否把属性修改为数据属性。直接在对象上定义的属性,它们这个特性的默认值为 true;
  • [[ enumerable ]]: 表示能否通过 for-in 循环返回属性。直接在对象上定义的属性,它们这个特性的默认值为 true;
  • [[ get ]]: 读取属性时,调用的函数。默认值为 undefined;
  • [[ set ]]: 写入属性时,调用的函数。默认值为 undefined;

访问器属性不能直接定义,必须通过Object.defintProperty()来定义。

"use strict"
let person = {
    name: '张三',
    age: 25
}
Object.defineProperty(person, 'oldAge', {
    get: function () {
        return this.age + 1;
    },
    set: function (newValue) {
        if (newValue > this.age) {
            this.age = newValue - 1;
            this.name = '李四'
        } else {
            this.age = newValue + 1;
            this.name = "王五"
        }
    }
})

person.oldAge = 28;
console.log(person); // {name: '李四', age: 27};
复制代码

上面定义了一个 person 对象。默认有两个属性, "name"、"age"。新增了一个访问器属性 "oldAge"。它包含了两个函数。 get 函数用来返回值。set函数,当为 "oldAge"写入值的时候,会调用。把 oldAge 设置为 27 后,调用 set 函数,改变了 person 对象的 "name" 和 "age" 属性值。

不一定非要同时指定 setget函数。只指定 get函数,意味着属性不能写,严格模式会报错。只指定了set函数,属性就不能读取,严格模式同样会报错。


定义多个属性

ES5 定义了一个 Object.defineProperties() 方法,可以通过描述符一次定义多个属性。这个方法,接受两个对象参数:第一个是要添加和修改其属性的对象,第二个就是要设置的属性的对象。

let car = {};
Object.defineProperties(car, {
    createYear: {
        writable: false,
        value: 2010
    },
    color: {
        writable: true,
        value: 'block'
    },
    severalYear: {
        get: function () {
            return parseInt(new Date().getFullYear()) - this.createYear
        },
        set: function (newValue) {
            if (newValue > 2010) {
                this.color = 'red';
            }
        } 
    }
})
console.log(car.createYear); // 2010
console.log(car.color);  // 'block'
console.log(car.severalYear); // 8
car.severalYear = 2015;
console.log(car.createYear); // 2010
console.log(car.color);  // 'red'
console.log(car.severalYear);  // 8
复制代码

需要注意的是:虽然我们设置 car.severalYear = 2015. 但是car.severalYear的值并没有改变。因为为访问器属性写入值的时候,只是会去执行 set 函数,而真实的值只能是通过get函数返回。


读取属性的特性

使用 ES5 的 Object.getOwnPropertyDescriptor()方法,可以取得给定属性的描述符。这个方法接受两个参数:

1、属性所在的对象。

2、属性名称。

返回值是一个对象,如果是数据属性,这个对象的属性有:configurableenumerablewritablevalue。 如果是一个访问器属性,对象的属性有:configurableenumerablegetset

let car = {};
Object.defineProperties(car, {
    createYear: {
        writable: false,
        value: 2010
    },
    color: {
        writable: true,
        value: 'block'
    },
    severalYear: {
        get: function () {
            return parseInt(new Date().getFullYear()) - this.createYear
        },
        set: function (newValue) {
            if (newValue > 2010) {
                this.color = 'red';
            }
        } 
    }
})

let descriptpor = Object.getOwnPropertyDescriptor(car, "createYear");
console.log(descriptpor);
// { value: 2010,
//   writable: false,
//   enumerable: false,
//   configurable: false }

let fangdescriptpor = Object.getOwnPropertyDescriptor(car, "severalYear");
console.log(fangdescriptpor); // 看下图
复制代码

在 JavaScript 中可以针对任何对象-----包括 DOM 和 BOM 对象使用 Object.getOwnPropertyDescriptor()方法。

转载于:https://juejin.im/post/5abce33e6fb9a028cf328eb2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值