defineProperty vue双向绑定

ECMA-262第5版在定义只有内部才用的特性(attribute)时,

描述了属性(property)的各种特征。

ECMA-262定义这些特性是为了实现javascript引擎用的,

对象的属性分为两种类型:数据属性访问器属性

1.数据属性数据属性是一个具有值的属性,该值可以是可写的,也可以是不可写的

1.访问器属性:访问器属性是由 getter 函数和 setter 函数所描述的属性。

一个描述符只能是这两者其中之一;不能同时是两者。

,给已有的数据属性加get或set转换为访问器属性时,其属性的value、writable就会被废弃。

configurable
当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。
enumerable
当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。

数据描述符还具有以下可选键值:

value

该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。
默认为 undefined
writable
当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变。

存取描述符还具有以下可选键值:

get
属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。
默认为 undefined
set
属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。
默认为 undefined
var person = new Object();person.name = 'Nicy';
var person = {name: 'Nicy'}
通过以上两种方式添加的对象属性,其布尔值特性默认值是true,通过Object.defineProperty来修改属性特性时,只设置需要修改的特性即可;
而通过Object.defineProperty创建的属性,其布尔值特性默认值是false。

Object.getOwnPropertyDescriptor 读取属性的特性

通过Object.defineProperties()可以一次性为对象定义多个属性

var person = {}
person.age='10';//添加的属性默认数据类型都是true
for(let key in person){
console.log(key,person[key]) // "age" "10"
}
person.age='20';//所以writable是true所以修改为name2,enumerable也是true在for in 可以找到

Object.defineProperty(person, "name", {value: 'Nicy'})
//defineProperty添加的属性默认数据类型都是false,所以writable是false,enumerable也是false无法进行枚举

person.name = 'Lee';//无法修改在非严格模式不报错,但是不执行。严格模式报错
console.log(person.name) //"Nicy" // 打印结果仍然是defineProperty的赋值 'Nicy'

Object.defineProperty(person, "name2", {
writable: true
})
person.name2 = 'Lee';
console.log(person.name2) // 'Lee'
for(let key in person){
console.log(key,person[key]) //"age" "20"
}
console.log(Object.getOwnPropertyDescriptor(person,'age'))
//{ value: "20", writable: true, enumerable: true, configurable: true }
console.log(Object.getOwnPropertyDescriptor(person,'name'))
//{ value: "20", writable: true, enumerable: true, configurable: true }
console.log(Object.getOwnPropertyDescriptor(person,'name2'))
//{ value: "Lee", writable: true, enumerable: false, configurable: false }

 

Vue内部实现时用到了ES5的Object.defineProperty()这个API,也正是这个原因,

所以Vue不支持IE8及以下浏览器(IE8及以下浏览器是不支持ECMASCRIPT 5的Object.defineProperty())。

vue双向绑定原理

当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty (ES5 中一个无法 shim 的特性)把这些属性全部转为 getter/setter

这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。

每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。

详细原理实现

https://blog.csdn.net/MeiLuan_yahoho/article/details/87912553

posted @ 2020-09-21 16:25  辛夷不改年年色  阅读(294)  评论(0)    收藏  举报