了解Object.defineProperty()

github源码

Object.defineProperty()方法直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象。

vueJS采用 ES5 提供的 Object.defineProperty() 方法,监控对数据的操作,从而可以自动触发数据同步。并且,由于是在不同的数据上触发同步,可以精确的将变更发送给绑定的视图,而不是对所有的数据都执行一次检测。

首先我们得先知道,ECMAScript中有两种属性:数据属性和访问器属性( ie8以下只能在dom对象上使用;不能使用在普通对象上)

数据属性:
  [[Configurable]]: 表示能否修改属性。默认值为true

  [[Enumerable]]: 表示属性是否可枚举,也就是是否可以通过for-in循环返回属性。默认值为true

  [[Writable]]: 表示能否修改属性的值。默认值为true

  [[value]]: 包含这个属性的值.读取属性的时候就是通过这里开始读。默认值为undefined
访问器属性:
   [[Configurable]]: 表示能否修改属性。默认值为true

   [[Enumerable]]: 表示属性是否可枚举,也就是是否可以通过for-in循环返回属性。默认值为true

   [[Get]]: 在读取属性时调用的函数,默认时undefined

   [[Set]]: 在设置属性时调用的函数,默认时undefined

    我们要是想修改默认属性的值就可以使用:Object.defineProperty(obj,prop,descriptor);

1.基本用法:

var a= {}
Object.defineProperty(a,"b",{
value:123
});
console.log(a.b);//123

2.参数介绍:

 第一个参数obj:目标对象a

 第二个参数prop:需要定义的属性或方法的名字"b"

 第二个参数descriptor:目标属性所拥有的特性

2.1 第三个参数的取值介绍(descriptor)

    value:属性的值

    writable:如果为false,属性的值就不能被重写,只能为只读了

    configurable:总开关,一旦为false,就不能再设置他的(value,writable,configurable)

    enumerable:是否能在for...in循环中遍历出来或在Object.keys中列举出来。

    get:后面介绍

    set:后面介绍

    注意:在 descriptor 中不能同时设置访问器(get 和 set)和 wriable 或 value,否则会错,就是说用 get 和 set,就不能用 writable 或 value 中的任何一个

在基本用法里只设置了value,没有设置别的,可以简单的理解为(暂时这样理解)它会默认帮我们把writable,configurable,enumerable。都设上值,而且值还都是false。(仅限于第一次设置的时候),等同于以下代码:

    var a = {};
Object.defineProperty(a, 'b', {
value: 123,
writable: false,
enumerable: false,
configurable: false
});
console.log(a.b); //123

2.1.1 configurable介绍

总开关,第一次设置 false 之后,,第二次什么设置也不行了:
也就是说,你可以使用Object.defineProperty()方法无限修改同一个属性,但是当把configurable改为false之后就有限制了 var a = {};
Object.defineProperty(a, 'b', {
configurable: false
});
Object.defineProperty(a, 'b',{
configurable: true
});
//报错:Uncaught TypeError: Cannot redefine property: b(…)

2.1.2 writable介绍

var a = {};
Object.defineProperty(a, 'b', {
value: 123,
writable: false //只读
});
console.log(a.b); // 打印 123
a.b = 124; // 没有错误抛出(在严格模式下会抛出,即使之前已经有相同的值)
console.log(a.b); // 打印 123, 赋值不起作用。

2.1.3 enumerable介绍

var a = {}
Object.defineProperty(a,"b",{
value:3445,
enumerable:true
});
console.log(Object.keys(a));// 打印["b"] //改成false: var a = {}
Object.defineProperty(a,"b",{
value:3445,
enumerable:false
});
console.log(Object.keys(a));// 打印[]

2.1.4 set & get

访问器属性不能直接定义!只能通过Object.defineProperty()来定义:
var a= {}
Object.defineProperty(a,"b",{
set:function(newValue){
console.log("赋值是:"+newValue)
},
get:function(){
console.log("取值:")
return 2 //注意这里,我硬编码返回2
}
});
a.b =1; //赋值是: 1
console.log(a.b) ; //取值 2 简单来说,这个 b 赋值或者取值的时候会分别触发 set 和 get 对应的函数

3.Object.defineProperty示例:

//判断是不是对象
function isObj(obj){
var type = Object.prototype.toString.call(obj);
return type === '[object Object]';
} //执行函数:
function objFun(obj){
if(isObj(obj)){
new Observer(obj);
}
} function Observer(obj){
this.data = obj;
this.walk(obj);
} //监听事件函数:
Observer.prototype.walk = function(obj){
for(var k in obj){
def(obj,k,obj[k])
}
} function def(obj,k,val){
Object.defineProperty(obj,k,{
configurable:true,
enumerable:true,
get:function(){
console.log('get取值');
return val;
},
set:function(newVal){
if(val === newVal){
return;
}
val = newVal;
console.log('set设置值')
}
});
} //测试:
var obj = {a:111,b:222};
objFun(obj);
console.log(obj.a)//get取值 222
obj.a = 333;//set设置值
console.log(obj)

4.Object.defineProperty实现数据和视图的联动:

html:

<div>
Object.defineProperty实现数据和视图的联动: <br>
<span id="nickName"></span>
<div id="introduce"></div>
</div> js:(视图控制器) var userInfo = {};
Object.defineProperty(userInfo,'nickName',{
get:function(){
return document.getElementById('nickName').innerHTML;
},
set:function(nick){
document.getElementById('nickName').innerHTML = nick
}
});
Object.defineProperty(userInfo,'introduce',{
get:function(){
return document.getElementById('introduce').innerHTML;
},
set:function(introduce){
document.getElementById('introduce').innerHTML = introduce
}
});
//console.log(userInfo)
userInfo.nickName = '我是nickName';
userInfo.introduce = '我是introduce' 上面设置userInfo的nickName属性时会调用set方法,更新DOM节点的HTML

系列文章的目录:

Vue双向绑定的实现原理系列(一):Object.defineproperty
Vue双向绑定的实现原理系列(二):设计模式
Vue双向绑定的实现原理系列(三):监听器Observer和订阅者Watcher
Vue双向绑定的实现原理系列(四):补充指令解析器compile

Vue双向绑定的实现原理系列(一):Object.defineproperty的更多相关文章

  1. Vue双向绑定的实现原理系列(四):补充指令解析器compile

    补充指令解析器compile github源码 补充下HTML节点类型的知识: 元素节点 Node.ELEMENT_NODE(1) 属性节点 Node.ATTRIBUTE_NODE(2) 文本节点 N ...

  2. Vue双向绑定的实现原理系列(三):监听器Observer和订阅者Watcher

    监听器Observer和订阅者Watcher 实现简单版Vue的过程,主要实现{{}}.v-model和事件指令的功能 主要分为三个部分 github源码 1.数据监听器Observer,能够对数据对 ...

  3. 梳理vue双向绑定的实现原理

    Vue 采用数据劫持结合发布者-订阅者模式的方式来实现数据的响应式,通过Object.defineProperty来劫持数据的setter,getter,在数据变动时发布消息给订阅者,订阅者收到消息后 ...

  4. Vue双向绑定的实现原理及简单实现

    vue数据双向绑定原理   vue数据双向绑定是通过(数据劫持)+(发布者-订阅者模式)的方式来实现的,而所谓的数据劫持就是通过Object.defineProperty() 来实现的,所谓的Obje ...

  5. Vue双向绑定原理,教你一步一步实现双向绑定

    当今前端天下以 Angular.React.vue 三足鼎立的局面,你不选择一个阵营基本上无法立足于前端,甚至是两个或者三个阵营都要选择,大势所趋. 所以我们要时刻保持好奇心,拥抱变化,只有在不断的变 ...

  6. vue双向绑定、Proxy、defineproperty

    本文原链接:https://www.jianshu.com/p/2df6dcddb0d7 前言 双向绑定其实已经是一个老掉牙的问题了,只要涉及到MVVM框架就不得不谈的知识点,但它毕竟是Vue的三要素 ...

  7. Vue.js双向绑定的实现原理和模板引擎实现原理(##########################################)

    Vue.js双向绑定的实现原理 解析 神奇的 Object.defineProperty 这个方法了不起啊..vue.js和avalon.js 都是通过它实现双向绑定的..而且Object.obser ...

  8. vue双向绑定的原理及实现双向绑定MVVM源码分析

    vue双向绑定的原理及实现双向绑定MVVM源码分析 双向数据绑定的原理是:可以将对象的属性绑定到UI,具体的说,我们有一个对象,该对象有一个name属性,当我们给这个对象name属性赋新值的时候,新值 ...

  9. vue实现双向绑定的简单原理: defineProperty

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

随机推荐

  1. Vue中的key到底有什么用?

    key是为Vue中的vnode标记的唯一id,通过这个key,我们的diff操作可以更准确.更快速 diff算法的过程中,先会进行新旧节点的首尾交叉对比,当无法匹配的时候会用新节点的key与旧节点进行 ...

  2. string字符串长度和字节长度问题

    string str = "abcdef 安安安"; int i = str.Length; byte[] bt = System.Text.Encoding.Default.Ge ...

  3. 不升级Element-UI 版本为时间选择器增加标记功能

    Element-UI里的date-picker是个优秀的时间选择器,支持的选项很多,定制型很强.不过date-picker在2.12版本之前并不支持自定义单元格样式,也就是2.12的cellClass ...

  4. vue +echarts树状图

    <template> <div :class="className" :id="id" :style="{height:height ...

  5. 第十章、os模块

    目录 第十章.os模块 一.os模块 第十章.os模块 一.os模块 方法 详解 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirn ...

  6. 记录-Intellij Idea下以Tomcat运行Web项目时的位置问题

    今天本来准备把原来的一个Web项目导入到Idea下,之前这个项目是用eclipse写的,容器用的tomcat,首先导入前我把一些没用的配置文件都给删了,像什么.eclipse..setting什么的, ...

  7. Eclipse配置Maven的本地仓库和阿里云镜像 加速Maven更新

    先确定自己电脑是否安装了Maven和安装位置,具体查询方法直接win+R键打开运行窗口,输入cmd打开dos窗口,再输入mvn -v即可查询安装的位置 拿到安装位置 D:\Applications\W ...

  8. [易学易懂系列|rustlang语言|零基础|快速入门|(5)|生命周期Lifetime]

    [易学易懂系列|rustlang语言|零基础|快速入门|(5)] Lifetimes 我们继续谈谈生命周期(lifttime),我们还是拿代码来说话: fn main() { let mut a = ...

  9. grub命令行和配置文件配置配置信息

    一.grub简介 GNU GRUB(简称“GRUB”)是一个来自GNU项目的启动引导程序.GRUB是多启动规范的实现,它允许用户可以在计算机内同时拥有多个操作系统,并在计算机启动时选择希望运行的操作系 ...

  10. loj2314 「NOIP2017」小凯的疑惑[同余最短路or数论]

    这题以前就被灌输了“打表找规律”的思想,所以一直没有好好想这道题,过了一年还不太会qwq.虽然好像确实很简单,但是还是带着感觉会被嘲讽的心态写这个题解...而且还有一个log做法不会... 法1:(一 ...