每周分享:彻底弄懂 defineProperty

Vue.js 的流行将其数据双向绑定的核心带到了大家面前,那就是 Object.defineProperty(),在详细讲解这个方法之前,我们先用一段最简单的代码实现一个最简单的数据响应。

<div id="main"></div>
let info = {}
Object.defineProperty(info, 'name', {
  get: function () {
    return document.getElementById('main').innerHTML
  },
  set: function (value) {
    document.getElementById('main').innerHTML = value
  }
})
info.name = "hello" 

这里当我们修改 info.name 的值的时候就会动态反馈到 HTML 元素上。这里的核心就是 set 定义了在给 info 对象设置值的时候会自动去执行 set 中的代码,从而达到了数据绑定的效果。起到了一个触发器的效果。

当然这仅仅是一个简单的示例,实际上 Vue.js 并不是单纯地通过数据和 DOM 节点的绑定来绑定数据,在此之间还有 WacherDirective,这里不细说,接下来主要看看 Object.defineProperty() 到底是什么。

作用

给指定对象加上新的属性或者修改原有属性的值

返回值

被操作的对象

语法

Object.defineProperty(obj, prop, descriptor)

参数

  • obj:要操作的对象
  • prop:要修改或新增的属性名称
  • descriptor:属性描述符

接下来着重讲讲属性描述符

属性描述符

属性描述符(descriptor) 顾名思义就是如何描述(设置)指定属性,分为两种:数据描述符存取描述符

数据描述符

可选键值有

value

要设置的具体值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined

writable

规定该属性是否可被赋值运算符(=)改变。默认为 false

var obj = {}
Object.defineProperty(obj, 'name', {
  value: 'lucy',
  writable: false
})

那么 obj{name: "lucy"},然后我们再修改

obj.name = 'tom'

此时 obj 仍然是 {name: "lucy"} ,因为我们定义了 name 属性的 writablefalse 是不能被赋值运算符修改的(注意这里并不会报错)。当然不设置 writable 的值也是可以的,因为其默认值就是 false

存取描述符

可选键值有

get

一个给属性提供 getter 的方法。当访问该属性时,该方法会被执行,默认为 undefined

set

一个给属性提供 setter 的方法,当属性值修改时,触发执行该方法,默认为 undefined

这俩其实就是在给属性赋值或者取值的时候的一个 触发器

var obj = {}
Object.defineProperty(obj, 'name', {
  set: function (value) {
  },
  get: function () {
  }
})

公共键值

除了上面两种描述符各自独有的键值,他们还有公共的键值可用

configurable

表示该属性是否可以被删除,以及除 writable 特性外的其他特性是否可以被修改。默认为 false

enumerable

定义了对象的属性是否可以在 for...in 循环和 Object.keys() 中被枚举。默认为 false

var obj = {
  age: 12
}
Object.defineProperty(obj, 'name', {
  value: 'tom',
  enumerable: false
})

这里 obj 变成了 {age: 12, name: "tom"} 但是我们执行

Object.keys(obj)

得到的却是 ["age"] ,可见 enumerable 确实影响到了 Object.keys() 的取值。当然直接写成下面这样也是可以的

Object.defineProperty(obj, 'name', {
  value: 'tom'
})

因为 enumerable 的默认值就是 false

注意,如果同时设置了数据描述符和存取描述符,是会出现异常的,比如我这样写

var obj = {}
Object.defineProperty(obj, 'name', {
  set: function (value) {
  },
  value: 'tom'
})

则会报错

 Invalid property descriptor. Cannot both specify accessors and a value or writable attribute

数据描述符默认值

需要注意的是,以两种不同的方式给属性赋值时,数据描述符中的属性默认值是不同的。

1、点运算

var obj = {}
obj.name = 'tom'

等价于

Object.defineProperty(obj, 'name', {
  value : 'tom',
  writable : true,
  configurable : true,
  enumerable : true
})

2、Object.defineProperty()

Object.defineProperty(obj, 'name', {
  value : 'tom',
})

等价于

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

最新评论

  1. I was curious if you ever considered changing the page layout of your blog? Its very well written; I love what youve got to say. But maybe you could a little more in the way of content so people could connect with it better. Youve got an awful lot of text for only having one or two images. Maybe you could space it out better? Francesco Zaffino

  2. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vestibulum tempus dapibus. In hac habitasse platea dictumst. Mauris finibus convallis efficitur. Curabitur lectus tellus, congue vitae dictum nec, tempor at sem. Maecenas finibus pretium ex, id lobortis eros interdum at. Proin porttitor dignissim cursus. Quisque consequat eros odio, quis interdum erat convallis ut. John Preble

  3. Thanks for your whole work on this website. My niece takes pleasure in working on research and it is simple to grasp why. We all notice all relating to the powerful ways you render vital tips and tricks via your website and therefore welcome response from website visitors on this topic while our own simple princess is without question understanding so much. Take pleasure in the rest of the year. Your performing a very good job. Mitchell Suprenant

  4. I agree with all of this but what is your response to the Blue Zones book and study which clearly has alcohol as linked those populations longevity? Those are not wealthy communities. They do obviously have many other factors that contribute to their health and well-being but the book clearly mentions small amounts of alcohol as a factor. I would appreciate your take on this! Thank you, Kelvin Churchill

  5. I have been browsing on-line greater than 3 hours as of late, yet I never discovered any interesting article like yours. It is beautiful worth enough for me. In my opinion, if all website owners and bloggers made good content material as you probably did, the internet can be much more helpful than ever before. Rosario Boucher

türk ifşa进行回复 取消回复

邮箱地址不会被公开。 必填项已用*标注