数据劫持
什么是数据劫持
-
Object.defineProperty()
-
给一个对象添加get和set方法,在我们通过类似于obj.
attribute获取属性的时候会调用get方法,通过obj.attribute = ***设置属性的时候会调用set方法,我们通过重写这个get,set方法就可以达到我们不可告人的目的-实现数据劫持
vue双向绑定原理
-
Vue内部通过
Object.defineProperty
方法属性拦截的方式,把data
对象里每个数据的读写转化成getter
/setter
,当数据变化时通知视图更新 -
在new Vue的时候,在Observer中通过Object.defineProperty()达到数据劫持,代理所有数据的getter和setter属性,在每次触发setter的时候,都会通过Dep来通知Watcher,Watcher作为Observer数据监听器与Compile模板解析器之间的桥梁,当Observer监听到数据发生改变的时候,通过Updater来通知Compile更新视图
-
VUE实现双向数据绑定的原理就是利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。它接收三个参数,要操作的对象,要定义或修改的对象属性名,属性描述符。重点就是最后的属性描述符。属性描述符是一个对象,主要有两种形式:数据描述符和存取描述符。这两种对象只能选择一种使用,不能混合两种描述符的属性同时使用。上面说的get和set就是属于存取描述符对象的属性。
-
在面试中如何应对?面试官:说一下VUE双向绑定的原理?答:VUE实现双向数据绑定的原理就是利用了Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。
-
代码演示:defineProperty的用法var obj = { };var name;//第一个参数:定义属性的对象。//第二个参数:要定义或修改的属性的名称。//第三个参数:将被定义或修改的属性描述符。Object.defineProperty(obj, "data", {//获取值get: function () {return name;},//设置值set: function (val) {name = val;console.log(val)}})//赋值调用setobj.data = 'aaa';//取值调用getconsole.log(obj.data);代码演示:defineProperty的双向绑定var obj={};Object.defineProperty(obj, 'val',{set:function (newVal) {document.getElementById("a").value =newValundefined?'':newVal;document.getElementById("b").innerHTML=newValundefined?'':newVal;}});document.getElementById("a").addEventListener("keyup",function (e) {obj.val = e.target.value;})
-
vue双向数据绑定是通过数据劫持结合发布订阅者模式来实现的。
也就是数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也跟着变化,核心方法是Object.defineProperty()
数据劫持示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<!-- <input type="" name="" id="input" value="" /><br />
<span id="span">我是初始值</span>
<script type="text/javascript">
const obj = {};
let text = ''
Object.defineProperty(obj, 'text', {
get: function () {
console.log('get val');
return text
},
set: function (newVal) {
console.log('set val:' + newVal);
text = newVal
}
});
const input = document.getElementById('input');
input.addEventListener('keyup', function (e) {
document.getElementById('span').innerHTML = obj.text = e.target.value;
})
</script> -->
<script type="text/javascript">
var Book = {};
var name = '';
Object.defineProperty(Book, 'name', {
set: function (value) {
name = value;
console.log('你取了一个书名叫:' + value);
},
get: function () {
console.log('get方法被监听到');
return '<' + name + '>';
}
});
Book.name = '人性的弱点'; //你取了一个书名叫:人性的弱点
console.log(Book.name); //<人性的弱点>
</script>
<!-- <script>
var obj3 = {};
var newv = {
a: 666
}
Object.defineProperty(obj3, 'newv', {
set(v) {
console.log(v);
},
get() {
return newv
}
})
obj3.newv.a = 222
</script> -->
<!-- <script>
var obj = {
name: 'tom'
}
var age = 24
Object.defineProperty(obj, 'age', {
enumerable: true,
configurable: false,
get() {
console.log('get', age);
return age
},
set(newVal) {
console.log('set', age, newVal);
age = newVal
}
})
obj.age = 20
console.log(obj);
</script> -->
</body>
</html>