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 节点的绑定来绑定数据,在此之间还有 Wacher 和 Directive,这里不细说,接下来主要看看 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 属性的 writable 为 false 是不能被赋值运算符修改的(注意这里并不会报错)。当然不设置 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
})
This piece of writing is genuinely a nice one it assists new web viewers, who are wishing in favor of blogging. Nicholas Sherief
Hello. This article was really motivating, especially since I was browsing for thoughts on this subject last Sunday. Heriberto Ringen
Goed produkt. alleen nergens verkrijgbaar behalve deze webshop. Marlon Lauterbach
Piece of writing writing is also a fun, if you be familiar with afterward you can write if not it is complicated to write. Paris Jerabek
I have recently started a site, the information you offer on this site has helped me greatly. Thanks for all of your time & work. Cary Mccombie