003 理解对象

在 JavaScript 中,每个对象都是基于另一个对象创建的,也叫做对象的原型。所有对象都是通过其原型对象创建出来的。
不同的对象都有各自的属性,ECMAScript 中有两种类型的属性:数据属性访问器属性
数据属性,就是最常见的有实实在在的值的属性,访问器属性则是那些通过 gettersetter 函数进行访问和赋值的属性。对于这两种属性,都有描述各自行为的特性。首先来看数据属性。

数据属性

数据属性有以下几个描述其行为的特性:

  • [[Configurable]]:此描述符表示是否能够删除该属性,默认为 true
  • [[Enumerable]]:此描述符表示该属性是否可以通过 for-in 循环枚举,默认为 true
  • [[Writable]]:此描述符表示该属性是否可写,默认为 true
  • [[Value]]:此描述符专门用来保存该属性的值,读取属性时,从这个位置读取,写入属性时(如果该属性可写的情况下),就写入在这个位置。该描述符的默认值为 undefined

访问器属性

访问器属性不包含具体的属性值,其包含了一对 gettersetter 函数(非必须),在读取属性值时,将调用 getter 函数,将此函数的返回值作为读取的值。在设置属性时,将调用 setter 函数,在该函数中完成对属性值的设置。
访问器属性有以下几个描述其行为的特性:

  • [[Configurable]]:同上
  • [[Enumerable]]:同上
  • [[Get]]:读取属性时调用的函数,默认值为 undefined
  • [[Set]]:设置属性时调用的函数,默认值为 undefined

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

Object.defineProperty() 方法

该方法用来对属性进行配置,包括数据属性和访问器属性。该函数接受三个参数:

  • 属性所在的对象
  • 属性名
  • 属性描述符对象

调用该方法返回被定义后的对象。
1.定义数据属性

let ball = {name:"basketball",brand:"NIKE"};
Object.defineProperty(ball,"name",{
    writable:false
}); //{name:"basketball",brand:"NIKE"}
ball.name = "pingpang";
ball.name //"basketball";

2.定义访问器属性

let ball = {}
Object.defineProperty(ball,"name",{
    get:function(){
        return this._name
    },
    set:function(name){
        this._name = name
    }
})
ball.name //undefined
ball.name = "篮球"
ball.name //"篮球"
ball._name //"篮球"
ball._name = "足球"
ball.name //"篮球"

getter 函数中,我们访问 name 属性时返回当前对象的 _name 属性,在 setter 函数中,我们设置 name 的值时会设置设置该对象的 _name 属性,也就是 name 属性的值始终依赖于 _name 属性的值,而当我们修改 _name 属性的值后,获取到的 name 属性的值也相应变化了。

关于 [[Configurable]] 描述符

一旦将 [[Configurable]] 设置为 false 后,该属性就变成了“不可配置”状态,此时,除了对 [[Writable]] 描述符进行配置外,进行其他的配置都会报错。

let ball = {}
Object.defineProperty(ball,"name",{
    configurable:false,
    value:"篮球"
})
// 再次配置
Object.defineProperty(ball,"name",{
    configurable:true,
})

此时会产生错误:

VM3119:1 Uncaught TypeError: Cannot redefine property: name

但是我们仍然可以对 [[Writable]] 描述符进行配置:

Object.defineProperty(ball,"name",{
    writable:false,
})
ball.name = "足球"
ball.name //"篮球"

定义多个属性

ES5 还提供了定义多个属性的方法:Object.defineProperties(),该方法接受两个参数,第一个参数是配置属性的对象,第二个参数是一个针对待配置属性的描述字典:

let ball = {}
Object.defineProperties(ball,{
    name:{
        writable:false
    },
    brand:{
        configurable:false
    }
})

获取属性特性

通过 Object.getOwnPropertyDescriptor() 方法,可以获取对象的属性的描述符。该方法接受两个参数:属性所在的对象和属性名。

let ball = {}
Object.defineProperties(ball,{
    name:{
        writable:false
    },
    brand:{
        configurable:false
    }
})
Object.getOwnPropertyDescriptor(ball,"name") //{value: undefined, writable: false, enumerable: false, configurable: false}

另外,还有一个 Object.getOwnPropertyDescriptors()方法,可以获取对象上所有的属性特性,该方法只接受一个对象作为参数,返回该对象所有的属性描述符:

Object.getOwnPropertyDescriptors(ball)

返回值:

{
brand: {value: undefined, writable: false, enumerable: false, configurable: false},
name: {value: undefined, writable: false, enumerable: false, configurable: false}
}

完。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,124评论 19 139
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 14,030评论 6 13
  • 博客内容:什么是面向对象为什么要面向对象面向对象编程的特性和原则理解对象属性创建对象继承 什么是面向对象 面向对象...
    _Dot912阅读 5,305评论 3 12
  • 《牧羊少年的奇幻之旅》随想二 1 你敢做自己么? 这个世界上我们有太多的不敢,不敢违抗父母,不敢违抗权威,更多的是...
    阿柒柒成长记阅读 3,644评论 0 2
  • 从前有一个偏远的村庄,村庄的不远处有一个山洞。村庄里流传着一个关于山洞的古老的传说,传说中说道:“山洞里居住着一个...
    海王星1984阅读 2,688评论 0 1

友情链接更多精彩内容