了解Object.defineProperty()

github源码

  1. Object.defineProperty()方法直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象。
  2. vueJS采用 ES5 提供的 Object.defineProperty() 方法,监控对数据的操作,从而可以自动触发数据同步。并且,由于是在不同的数据上触发同步,可以精确的将变更发送给绑定的视图,而不是对所有的数据都执行一次检测。

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

数据属性:
  1. [[Configurable]]: 表示能否修改属性。默认值为true
  2. [[Enumerable]]: 表示属性是否可枚举,也就是是否可以通过for-in循环返回属性。默认值为true
  3. [[Writable]]: 表示能否修改属性的值。默认值为true
  4. [[value]]: 包含这个属性的值.读取属性的时候就是通过这里开始读。默认值为undefined
访问器属性:
  1. [[Configurable]]: 表示能否修改属性。默认值为true
  2. [[Enumerable]]: 表示属性是否可枚举,也就是是否可以通过for-in循环返回属性。默认值为true
  3. [[Get]]: 在读取属性时调用的函数,默认时undefined
  4. [[Set]]: 在设置属性时调用的函数,默认时undefined
  5. 我们要是想修改默认属性的值就可以使用:Object.defineProperty(obj,prop,descriptor);

1.基本用法:

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

2.参数介绍:

  1. 第一个参数obj:目标对象a
  2. 第二个参数prop:需要定义的属性或方法的名字"b"
  3. 第二个参数descriptor:目标属性所拥有的特性

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

  1. value:属性的值
  2. writable:如果为false,属性的值就不能被重写,只能为只读了
  3. configurable:总开关,一旦为false,就不能再设置他的(valuewritableconfigurable
  4. enumerable:是否能在for...in循环中遍历出来或在Object.keys中列举出来。
  5. get:后面介绍
  6. set:后面介绍
  7. 注意:在 descriptor 中不能同时设置访问器(get set)和 wriable value,否则会错,就是说用 get set,就不能用 writable value 中的任何一个
  8. 在基本用法里只设置了value,没有设置别的,可以简单的理解为(暂时这样理解)它会默认帮我们把writableconfigurableenumerable。都设上值,而且值还都是false。(仅限于第一次设置的时候),等同于以下代码:
  9. var a = {};
  10. Object.defineProperty(a, 'b', {
  11. value: 123,
  12. writable: false,
  13. enumerable: false,
  14. configurable: false
  15. });
  16. console.log(a.b); //123

2.1.1 configurable介绍

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

2.1.2 writable介绍

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

2.1.3 enumerable介绍

  1. var a = {}
  2. Object.defineProperty(a,"b",{
  3. value:3445,
  4. enumerable:true
  5. });
  6. console.log(Object.keys(a));// 打印["b"]
  7. //改成false:
  8. var a = {}
  9. Object.defineProperty(a,"b",{
  10. value:3445,
  11. enumerable:false
  12. });
  13. console.log(Object.keys(a));// 打印[]

2.1.4 set & get

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

3.Object.defineProperty示例:

  1. //判断是不是对象
  2. function isObj(obj){
  3. var type = Object.prototype.toString.call(obj);
  4. return type === '[object Object]';
  5. }
  6. //执行函数:
  7. function objFun(obj){
  8. if(isObj(obj)){
  9. new Observer(obj);
  10. }
  11. }
  12. function Observer(obj){
  13. this.data = obj;
  14. this.walk(obj);
  15. }
  16. //监听事件函数:
  17. Observer.prototype.walk = function(obj){
  18. for(var k in obj){
  19. def(obj,k,obj[k])
  20. }
  21. }
  22. function def(obj,k,val){
  23. Object.defineProperty(obj,k,{
  24. configurable:true,
  25. enumerable:true,
  26. get:function(){
  27. console.log('get取值');
  28. return val;
  29. },
  30. set:function(newVal){
  31. if(val === newVal){
  32. return;
  33. }
  34. val = newVal;
  35. console.log('set设置值')
  36. }
  37. });
  38. }
  39. //测试:
  40. var obj = {a:111,b:222};
  41. objFun(obj);
  42. console.log(obj.a)//get取值 222
  43. obj.a = 333;//set设置值
  44. console.log(obj)

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

  1. html:
  2. <div>
  3. Object.defineProperty实现数据和视图的联动: <br>
  4. <span id="nickName"></span>
  5. <div id="introduce"></div>
  6. </div>
  7. js:(视图控制器)
  8. var userInfo = {};
  9. Object.defineProperty(userInfo,'nickName',{
  10. get:function(){
  11. return document.getElementById('nickName').innerHTML;
  12. },
  13. set:function(nick){
  14. document.getElementById('nickName').innerHTML = nick
  15. }
  16. });
  17. Object.defineProperty(userInfo,'introduce',{
  18. get:function(){
  19. return document.getElementById('introduce').innerHTML;
  20. },
  21. set:function(introduce){
  22. document.getElementById('introduce').innerHTML = introduce
  23. }
  24. });
  25. //console.log(userInfo)
  26. userInfo.nickName = '我是nickName';
  27. userInfo.introduce = '我是introduce'
  28. 上面设置userInfonickName属性时会调用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. Pr PS 笔记

    1. 保存窗口配置    窗口-新建工作区 2. 添加快捷键  编辑-自定义快捷键 3. 添加关键帧,需要下拉轨道 4. 关闭PR声音 5. 视频稳定器 选中素材,右键选择嵌套,嵌套后在子序列把视频画 ...

  2. Access to XMLHttpRequest at 'http://localhost:8090/user/getotp' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

    ajax跨域请求错误 解决: springboot中: 加注解 @CrossOrigin

  3. beego注解路由的格式

    原文: https://blog.csdn.net/weixin_33743880/article/details/88016192 beego注解路由的注释,我们可以把我们的注释分为以下类别: @T ...

  4. 上班时能不能戴耳机?V

    上班时能不能戴耳机? 新入职一公司, 上班时间不能戴耳机在V站一石激起千层浪,网友意见主要分几派: 甩手走人型: 神经病公司,这还不赶紧走 不走等着过年 不走留着转正 离职,下一题 还是赶紧离职吧 这 ...

  5. 《python解释器源码剖析》第10章--python虚拟机中的一般表达式

    10.0 序 上一章中,我们通过PyEval_EvalFrameEx看到了python虚拟机的整体框架,那么这一章我们将深入到PyEval_EvalFrameEx的各个细节当中,深入剖析python的 ...

  6. python中的__init_subclass__是什么?

    什么是__init_subclass__ class Hook: def __init_subclass__(cls, **kwargs): print("__init_subclass__ ...

  7. 使用Gallery制作图片浏览器

    MainActivity.class public class MainActivity extends AppCompatActivity implements AdapterView.OnItem ...

  8. postman 接口测试(一)

    一.postman 应用场景 开发接口快速的调用接口,以便调试 方便的调用接口,通过不同的参数去测试接口的输出 这些接口调用时需要保存下来的反复运行的 在运行中如果有断言(检查点 <预期 和现实 ...

  9. JNetPcap安装及使用

    啥是JNetPcap? JNetPcap是由Sly Technologies开发的开源DPI(Deep Packet Inspection)SDK. Java平台底层不支持底层网络操作,需要通过JNI ...

  10. java8学习之Function与BiFunction函数式接口详解

    Function接口: 上次中已经使用了Function的apply()方法,但是在这个接口中还存在三个具体实现的方法,如下: 下面来仔细的将剩下的方法学习一下: compose(): 首先来读一下该 ...