JavaScript学习笔记: Object.defineProperty()

前段时间在学习Vue的双向绑定原理及实现时,简单的知道Object.defineProperty()有很大的用处。这个方法会直接在一个对象上定义一个新属性,或者修改一个对象现有的属性,并返回这个对象。感觉他非常强大,但并不知道其中原委。回过头来重新补一下这方面的基础知识。

对象定义属性和赋值

在对象中,我们有很多种方式给其定义属性和赋值。最常见的是obj.prop = valueobj['prop'] = value。比如:

let Person = {}

Person.name = '大漠'
Person['age'] = 35

console.log(Person)

Object.defineProperty()

除了上述的方式之外,还可以使用Object.defineProperty()方法来定义和修改对象属性。下面我们就来好好的探讨一下这个方法。

Object.defineProperty()语法

Object.defineProperty()的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性,并返回这个对象,我们先来看一下怎么使用这个方法:

Object.defineProperty(obj, prop, descriptor)

这个方法有三个参数:

  • obj:需要被定义(或修改)属性的那个对象
  • prop:需要被定义(或修改)的属性名
  • descriptor:定义(或修改)的属性prop的描述

其返回值是被传递给函数的对象。

该方法允许精确添加或修改对象的属性。一般情况下,为对象添加属性是通过赋值来创建并显示在属性枚举中(for...inObject.keys方法),但这种方式添加的属性值可以被改变,也可以被删除。而使用Object.defineProperty()则允许改变这些额外细节的默认设置。例如,默认情况下,使用Object.defineProperty()增加的属性值是不可改变的。

属性特性和内部属性

JavaScript中有三种类型的属性:

  • 命名数据属性:拥有一个确定的值的属性。这也是最常见的属性
  • 命名访问器属性:通过gettersetter进行读取和赋值的属性
  • 内部属性:由JavaScript引擎内部使用的属性,不能通过JavaScript代码直接访问到,不过可以通过一些方法间接的读取和设置。比如,每个对象都有一个内部属性[[Prototype]],你不能直接访问这个属性,但可以通过Object.getPrototypeOf()方法间接的读取到它的值。虽然内部属性通常用一个双吕括号包围的名称来表示,但实际上这并不是它们的名字,它们是一种抽象操作,是不可见的,根本没有上面两种属性有的那种字符串类型的属性名

属性特性

对象中每个属性都有四个特性。两种类型的属性一共有六个属性特性:

  • 命名数据属性特有的特性:属性的值的[[Value]]特性和控制属性的值是否可以修改的[[Writable]]特性
  • 命名访问器属性特有的特性:存储着getter方法的[[Get]]和存储着setter方法的[[Set]]
  • 两种属性都有的特性:如果一个属性是不可枚举的,则一些操作下,这个属性是不可见的,比如for...inObject.keys,那么可以通过[[Enumerable]]特性来设置;如果一个属性是不可配置的,则该属性的所有特性([[Value]])都不可改变,那么可以通过[[Configurable]]特性来设置

内部属性

除了上面所说的之外,下面几个是所有对象都有的内部属性:

  • [[Prototype]]:对象的原型
  • [[Extensible]]:对象是否可扩展,也就是是否可以添加新的属性
  • [[DefineOwnProperty]]:定义一个属性的内部方法
  • [[Put]]:为一个属性赋值的内部方法

属性描述符

对象里目前存在的属性描述符有两种主要形式:数据描述符存取描述符

  • 数据描述符:是一个拥有可写或不可写值的属性
  • 存取描述符:是由一对 gettersetter 函数功能来描述的属性

描述符必须是两种形式之一;不能同时是两者。另外,属性描述符可以将一个属性的所有特性编码成一个对象并返回。例如:

Object.defineProperty(obj, 'key', {
    enumerable: false,
    configurable: false,
    writable: false,
    value: 'static'
})

属性描述符除了在Object.defineProperty()中使用之外,还常常使用在Object.getOwnPropertyDescriptor()Object.create()中。如果对象中的某个属性省略了属性描述符,则该属性会取一个默认值:

属性名 默认值
value undefined
get undefined
set undefined
writable false
enumerable false
configurable false

先对属性描述符做一个简单的归纳,因为后面接下来的篇幅都将围绕着Object.defineProperty()的属性描述符descriptor来展开的。

数据描述符和存取描述均具有以下可选键值

configurable:这个特性决定了对象的属性是否可以被删除,以及除writable特性外的其它特性是否可以被修改;并且writable特性值只可以是false。默认为false。同样通过示例来帮助我们理解这个描述符的特性:

剩余80%内容付费后可查看
* 请输入阅读码(忘记阅读码?

如需转载,烦请注明出处:https://www.w3cplus.com/javascript/object-defineproperty.html

如果文章中有不对之处,烦请各位大神拍正。如果你觉得这篇文章对你有所帮助,打个赏,让我有更大的动力去创作。(^_^)。看完了?还不过瘾?点击向作者提问!

赏杯咖啡,鼓励他创作更多优质内容!
返回顶部