自己在使用vue的过程中经常会用到听到数据双向绑定这个词,而且我们还可以直接通过调用this.msg(this表示vue实例),来获取data上的数据,以前一直不太明白为什么可以这样获取,直到有一天我在论坛里看到了寻找海蓝96这位大佬写的文章,才明白其原理,所以在此记录一下。

1、Object.defineProperty(obj,key,descriptor)

  Object.defineProperty主要是通过Get和Set这两个访问器属性来实现数据双向绑定的。说到这里必须先介绍以下js对象的两种特性。 ECMAScript中有两种属性:数据属性和访问器属性。这是js中任何对象都拥有的特性。

数据属性主要是用于对数据的描述。数据属性主要有以下4个特性。
1、Configurable:(字面意思是可配置的,我理解为可操作(删除、修改))表示能否通过delete操作来删除属性,以及能否修改属性,或者能否将属性修改为访问器属性。直接定义在对象上的属性,该特性值默认为true。
2、Enumerable:字面意思是可枚举的,表示能否通过for-in循环来遍历属性。直接在对象上定义的属性,该特性值默认为true。
3、Writable:表示能否修改属性的值。直接定义在对象上的该特性值默认也为true。
4、Value:这个特性包含着属性的数据值。对对象属性的读写操作都是在这个特性上。该特性的默认值为undefined。

  想要修改上面的4个特性就得调用Object.defineProperty(obj,key,descriptor)方法,descriptor表示的是一个对象,对象中的属性必须是这四个特性中的一项或多项。

注意: 1、多次调用Object.defineProperty()方法修改同一个属性,只要把configurable特性设置为false后,就不能再把它变成可配置的了(再次调用Object.defineProperty()将configurable特性设置为true会报错),即这个过程是不可逆的,不能再对对象属性进行delete操作,但是还可以对对象属性进行修改操作。

Object.defineProperty(obj,"name",{configurable:false,enumerable:true,writable:true,value:"james"
});
delete obj.name;
console.log(obj);//{name: "james"},可见不能对obj进行删除操作了。
obj.name="test";
console.log(obj.name);//test 还是可以对属性进行修改
复制代码

2、调用Object.defineProperty()方法时,如果不指定Configurable、Enumerable和writable等特性的值,默认为false。

访问器属性也有4个。但是不包含数据值
1、Configurable:(字面意思是可配置的,我理解为可操作(删除、修改))表示能否通过delete操作来删除属性,以及能否修改属性,或者能否将属性修改为访问器属性。直接定义在对象上的属性,该特性值默认为true。
2、Enumerable:字面意思是可枚举的,表示能否通过for-in循环来遍历属性。直接在对象上定义的属性,该特性值默认为true。
3、Get:在读取属性时调用的函数。 默认值为undefined。
4、Set:在写入属性时调用的函数。的默认值为undefined。

注意:不能使用Object.defineProperty()方法同时修改默认数据属性和访问器属性。即set和get访问器属性不能与writable以及value特性共存。

Object.defineProperty(obj,"name",{configurable:true,enumerable:true,writable:true,value:"james",get(){return this.val;},set(newVal){this.val=newval;}
});
//Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object>
复制代码

  个人觉得数据属性和访问器属性的Configurable和Enumerable没什么区别。访问器属性主要用的是Get和Set这两个。

可以通过Object.defineProperty()实现简单的数据双向绑定。实现代码如下:

<input id="test1"/>
<input id="test2"/>
<script>let obj={};Object.defineProperty(obj,"name",{configurable:true,enumerable:true,writable:true,// value:"",set(newValue){document.querySelector("#test1").value=newValue;document.querySelector("#test2").value=newValue;},get(){return obj["name"];}});document.addEventListener("keyup",function(e){obj.name=e.target.value;})
</script>//通过操作可以发现,在test1中输入会改变test2中的值,在test2中输入也能改变test1中的值。
复制代码

vue中为什么可以直接通过this.msg获取到data中的msg,原理代码如下:

    class Vue{constructor(options={}){this.$options=options;this._data=options.data;let data=this._data;Object.keys(data).forEach((key)=>{this._proxy(key)})};_proxy(key){//以this做为obj,将data对象上的属性全部绑定到vue实例上来Object.defineProperty(this,key,{configurable:true,enumerable:true,get(){return this._data[key];},set(newval){this._data[key]=newval;}})}}
复制代码

转载于:https://juejin.im/post/5cfcf9806fb9a07ec27b96aa

对javscript中Object.defineProperty的理解相关推荐

  1. Object.defineProperty()个人理解

    Object.defineProperty()个人理解 Object.defineProperty()用于定义对象中属性的特性,这些特性属于对象内部值,因此在JS中不能直接访问它们. 在ES5中,有两 ...

  2. [vue] 说说你对Object.defineProperty的理解

    [vue] 说说你对Object.defineProperty的理解 Object.defineProperty定义新属性或修改原有的属性: vue的数据双向绑定的原理就是用的Object.defin ...

  3. 如何理解JavaScript中Object.defineProperty【一】

    前言 当我们了解一个方法时,建议从以下几个维度着手 1.方法的定义 2.了解方法的使用场景 3.在场景中解决什么问题 带着这样的好奇心,去学习.研究,我们可能更好的理解.掌握.运用它 复制代码 定义 ...

  4. Object.defineProperty的理解

    一.Object.defineProperty:给一个对象定义一个新的属性或修改一个对象现有的属性,并且返回这个对象 1.语法:Object.defineProperty(参数1,参数2,参数3) 参 ...

  5. 基于Object.defineProperty实现双向数据绑定

    双向数据绑定可算是前端领域经久不衰的热词,不管是前端开发还是面试都会有所涉及.而且不同的框架也想尽一切办法去实现这一特性,比如: Knockout / Backbone --- 发布-订阅模式 Ang ...

  6. [OHIF-Viewers]医疗数字阅片-医学影像-Module: Panel-自定义面板-中-es6-Object.defineProperty()定义属性...

    [OHIF-Viewers]医疗数字阅片-医学影像-Module: Panel-自定义面板-中-Object.defineProperty()定义属性 Object.defineProperty()  ...

  7. 关于Object.defineProperty中enumerable: false不可枚举的理解

    文章目录 能否被for-in循环 对象的可枚举性除了会影响for-in还会影响Object.keys()和JSON.stringify方法 Object.defineProperty的enumerab ...

  8. vue中实现双向数据绑定原理,使用了Object.defineproperty()方法,方法简单

    在vue中双向数据绑定原理,我们一般都是用v-model来实现的 ,但一般在面试话会问到其实现的原理, 方法比较简单,就是利用了es5中的一个方法.Object.defineproperty(),它有 ...

  9. 理解Object.defineProperty的作用

    对象是由多个名/值对组成的无序的集合.对象中每个属性对应任意类型的值. 定义对象可以使用构造函数或字面量的形式: var obj = new Object; //obj = {} obj.name = ...

最新文章

  1. CoffeeScript 存在操作符“?” 详解
  2. QLogic改进ASP合作计划满足共享闪存缓存市场需求
  3. ACM练习 校赛83C:纸片儿(测试用例通过但WA/TLE)
  4. mysql那些事(6) WHERE条件 字符串的引号
  5. Netty入门笔记-I/O多路复用技术
  6. linux性能监控sar命令详解
  7. Java学习笔记之方法
  8. SQL 常用语句大全
  9. element表格点击行即选中该行复选框
  10. attrib批量显示文件夹_CMD中使用attrib命令设置文件只读、隐藏属性详解
  11. 智慧旅游系统总体设计方案
  12. fastboot驱动安装问题——文件哈希值不在指定目录
  13. ibm java虚拟机_IBM java VM 最新版的java虚拟机下载及安装的一点说明
  14. 精简迅雷绿色单文件版
  15. matlab gui矩阵计算器,matlab-gui矩阵计算器.doc
  16. 素数筛【埃筛,欧拉筛(线性筛)】
  17. python新版个人所得税代码_python-计算个人所得税(示例代码)
  18. Drupal项目实战-公司订餐系统
  19. 【转载】用Python计算身份证校验码
  20. Qt-QCustomPlot

热门文章

  1. BIEE-CSS样式大全
  2. java遍历给定目录,树形结构输出所有文件,包括子目录中的文件
  3. 关于登录记住密码使用cookie的详解
  4. php函数:register_shutdown_function
  5. FCKeditor如何升级CKEditor及使用方法
  6. Win32 API消息函数:GetMessagePos
  7. IPV6的设置问题!
  8. 欧拉角和旋转矩阵相互转换
  9. C++拾趣——STL容器的插入、删除、遍历和查找操作性能对比(ubuntu g++)——插入
  10. php修改时区MST,4、修改Cacti绘图的时间精度