【Vue】-- 数据双向绑定的原理 --Object.defineProperty()
Object.defineProperty()方法被许多现代前端框架(如Vue.js,React.js)用于数据双向绑定的实现,当我们在框架Model层设置data时,框架将会通过Object.defineProperty()方法来绑定所有数据,并在数据变化的同时修改虚拟节点,最终修改页面的Dom结构。
一、语法
Object.defineProperty(obj, prop, descriptor)
返回值
二、描述符(descriptor)说明
数据描述符和访问器描述符各自都是对象,有以下键值对:
configurable(必须) |
仅当设置的属性的描述符需要被修改或需要通过delete来删除该属性时,configurable属性设置为true。默认为false。 |
enumerable(必须) |
仅当设置的属性需要被枚举器(如for…in)访问时设置为true。默认为false。 |
value(可选) |
设置属性的值,可以是任何JavaScript值类型(number,object,function等类型)。默认为undefined。 |
writable(可选) |
仅当属性的值可以被赋值操作修改时设置为true。默认为false。 |
访问器描述符可以包含以下可选键值对:
get |
属性的getter方法,若属性没有getter方法则为undefined。该方法的返回为属性的值。默认为undefined |
set |
属性的setter方法,若属性没有setter方法则为undefined。该方法接收唯一的参数,作为属性的新值。默认为undefined。 |
// using __proto__
var obj = {};
var descriptor = Object.create(null); // no inherited properties //所有描述符的属性被设置为默认值
descriptor.value = 'static';
Object.defineProperty(obj, 'key', descriptor); //明确设置每个描述符的属性
Object.defineProperty(obj, 'key', {
enumerable: false,
configurable: false,
writable: false,
value: 'static'
}); //重用同一个对象作为描述符
function withValue(value) {
var d = withValue.d || (
withValue.d = {
enumerable: false,
writable: false,
configurable: false,
value: null
}
);
d.value = value;
return d;
}
Object.defineProperty(obj, 'key', withValue('static')); //如果Object.freeze方法可用,则使用它来防止对对象属性的修改
(Object.freeze || Object)(Object.prototype);
使用示例
创建一个属性
var o = {}; //创建一个对象
//使用数据描述符来为对象添加属性
Object.defineProperty(o, 'a', {
value: 37,
writable: true,
enumerable: true,
configurable: true
});
//属性”a”被设置到对象o上,并且值为37
//使用访问器描述符来为对象添加属性
var bValue = 38;
Object.defineProperty(o, 'b', {
get: function() { return bValue; },
set: function(newValue) { bValue = newValue; },
enumerable: true,
configurable: true
});
o.b; //
//属性”b”被设置到对象o上,并且值为38。
//现在o.b的值指向bValue变量,除非o.b被重新定义
//你不能尝试混合数据、访问器两种描述符
Object.defineProperty(o, 'conflict', {
value: 0x9f91102,
get: function() { return 0xdeadbeef; }
});
//抛出一个类型错误: value appears only in data descriptors, get appears only in accessor descriptors(value只出现在数据描述符中,get只出现在访问器描述符中)
修改一个属性
可写特性-writable
var obj = {};
Object.defineProperty(obj,"name",{
value:"张三",
writable:false//当设置为false的时候当前对象的属性值不允许被修改
})
obj.name="李四"
console.log(obj.name)//张三
var obj = {};
Object.defineProperty(obj,"name",{
value:"张三",
writable:true//当设置为true的时候当前对象的属性值允许被修改
})
obj.name="李四"
console.log(obj.name)//李四
可枚举特性-enumerable
var obj = {name:"张三",age:"李四"}
Object.defineProperty(obj,"name",{
enumerable:false//当设置为false的时候对象的属性不可被枚举
})
Object.defineProperty(obj,"age",{
enumerable:false
})
console.log(Object.keys(obj))//[]
var obj = {name:"张三",age:"李四"}
Object.defineProperty(obj,"name",{
enumerable:true//当设置为true的时候对象的属性可被枚举
})
Object.defineProperty(obj,"age",{
enumerable:true
})
console.log(Object.keys(obj))//["name",age]
可配置特性-configurable
var obj = {};
Object.defineProperty(obj,"name",{
value:"张三",
configurable:false//当设置为false的时候对象的属性不允许被删除
})
delete obj.name;
console.log(obj.name)//张三
var obj = {};
Object.defineProperty(obj,"name",{
value:"张三",
configurable:true//当设置为true的时候对象的属性允许被删除
})
delete obj.name;
console.log(obj.name)//undefined
get和set
Get:指读取属性时调用的函数。
Set:指写入属性时调用的函数
var obj = {name:"张三"}
Object.defineProperty(obj,"name",{
get(){
console.log("被访问了")//当被访问的时候会触发get()方法
},
set(newVal){
console.log("被设置了"+newVal)//当被设置的时候会触发set()方法
}
})
obj.name//输出:被访问了
obj.name="李四";//输出:被设置了李四
添加属性时的默认值
var o = {};
o.a = 1;
//等同于:
Object.defineProperty(o, 'a', {
value: 1,
writable: true,
configurable: true,
enumerable: true
});
//另一方面,
Object.defineProperty(o, 'a', { value: 1 });
//等同于:
Object.defineProperty(o, 'a', {
value: 1,
writable: false,
configurable: false,
enumerable: false
});
configurable和writable
var a={};
Object.defineProperty(a,"o",{
configurable:false,
value:10,
writable:true
});
console.log(a.o);//10
a.o=12;//不报错
console.log(a.o);//12
Object.defineProperty(a,"o",{
configurable:false,
value:14,
writable:true
});
console.log(a.o);//14
Object.defineProperty(a,"o",{
configurable:false,
value:14,
writable:false
});
a.o=16;//不报错
console.log(a.o);//14
//报错
Object.defineProperty(a,"o",{
configurable:false,
value:16,
writable:false
});
【Vue】-- 数据双向绑定的原理 --Object.defineProperty()的更多相关文章
- vue数据双向绑定的原理、虚拟dom的原理
vue数据双向绑定的原理https://www.cnblogs.com/libin-1/p/6893712.html 虚拟dom的原理https://blog.csdn.net/u010692018/ ...
- 西安电话面试:谈谈Vue数据双向绑定原理,看看你的回答能打几分
最近我参加了一次来自西安的电话面试(第二轮,技术面),是大厂还是小作坊我在这里按下不表,先来说说这次电面给我留下印象较深的几道面试题,这次先来谈谈Vue的数据双向绑定原理. 情景再现: 当我手机铃声响 ...
- Vue数据双向绑定原理及简单实现
嘿,Goodgirl and GoodBoy,点进来了就看完点个赞再go. Vue这个框架就不简单介绍了,它最大的特性就是数据的双向绑定以及虚拟dom.核心就是用数据来驱动视图层的改变.先看一段代码. ...
- vue数据双向绑定原理
vue的数据双向绑定的小例子: .html <!DOCTYPE html> <html> <head> <meta charset=utf-> < ...
- Vue数据双向绑定原理(vue2向vue3的过渡)
众所周知,Vue的两大重要概念: 数据驱动 组件系统 1 2 接下来我们浅析数据双向绑定的原理 一.vue2 1.认识defineProperty vue2中的双向绑定是基于definePropert ...
- 【学习笔记】剖析MVVM框架,简单实现Vue数据双向绑定
前言: 学习前端也有半年多了,个人的学习欲望还比较强烈,很喜欢那种新知识在自己的演练下一点点实现的过程.最近一直在学vue框架,像网上大佬说的,入门容易深究难.不管是跟着开发文档学还是视频教程,按步骤 ...
- Vue实现双向绑定的原理以及响应式数据
一.vue中的响应式属性 Vue中的数据实现响应式绑定 1.对象实现响应式: 是在初始化的时候利用definePrototype的定义set和get过滤器,在进行组件模板编译时实现water的监听搜集 ...
- vue双向数据绑定的原理-object.defineProperty() 用法
有关双向数据绑定的原理 关于数据双向绑定的理解:利用了 Object.defineProperty() 这个方法重新给对象定义了新属性,在操作新属性分别为为获取属性值(调用get方法)和设置属性值(调 ...
- 深入理解Proxy 及 使用Proxy实现vue数据双向绑定
阅读目录 1.什么是Proxy?它的作用是? 2.get(target, propKey, receiver) 3.set(target, propKey, value, receiver) 4.ha ...
随机推荐
- 利用zabbix api添加、删除、禁用主机
python环境配置yum -y install python-pip安装argparse模块pip install -i https://pypi.douban.com/simple/ argpar ...
- 中国剩余定理 CRT
中国剩余定理 CRT 正常版本CRT 要解的是一个很容易的东西 \[ \begin{aligned} x\equiv a_1(mod\ m_1)\\ x\equiv a_2(mod\ m_2)\\ . ...
- rt-thread 之网络组件
@2019-02-23 [小记] 文件 <net_sockets.c> 为兼容标准 BSD Socket API 文件 <sal_socket.c> 为网络中间抽象层 文件 & ...
- 什么是Tensor
https://blog.csdn.net/kansas_lh/article/details/79321234 tensor是tensorflow基础的一个概念——张量. Tensorflow用到了 ...
- 第三十七节、人脸检测MTCNN和人脸识别Facenet(附源码)
在说到人脸检测我们首先会想到利用Harr特征提取和Adaboost分类器进行人脸检测(有兴趣的可以去一看这篇博客第九节.人脸检测之Haar分类器),其检测效果也是不错的,但是目前人脸检测的应用场景逐渐 ...
- python 学习地址
本章主要记录学习python过程中借鉴的一些网站,并感谢这些博主辛勤付出. python官网:https://www.python.org/ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ...
- 分布式监控系统开发【day38】:主机存活检测程序解析(七)
一.目录结构 二.入口 1.文件MonitorServer.py import os import sys if __name__ == "__main__": os.enviro ...
- 第十四节:Lambda、linq、SQL的相爱相杀(3)
一. SQL 开篇 1. where用法 #region 封装EF调用SQL语句查询 public static List<T> ExecuteQuery<T>(string ...
- ConcurrentLinkedQueue使用和方法介绍
定义 一个基于链接节点的无界线程安全队列.此队列按照 FIFO(先进先出)原则对元素进行排序.队列的头部 是队列中时间最长的元素.队列的尾部 是队列中时间最短的元素.新的元素插入到队列的尾部,队列获取 ...
- windows系统调试MapReduce程序
如果使用windows开发mapreduce程序,是不能进行debug的,会报如下错误,但其实不影响最终运行结果 DEBUG o.a.h.u.Shell - Failed to detect a va ...