此文章将带领大家了解Object.defineProperty()的参数,及简单的双向数据绑定的实现。
vue 双向数据绑定的原理(常见面试题)
Object.defineProperty() 的作用就是直接在对象是定义一个新属性;或者修改一个已经存在的属性,并返回这个对象。
语法:Object.defineProperty ( obj , prop , desc )
··· | Object.defineProperty ( obj , prop , desc ) |
---|---|
obj | 目标对象 |
prop | 要修改或者要添加的属性名称 |
desc | 配置项,一个描述符对象,6个配置控制属性 {value,writable,configurable,enumerable,get,set} |
1、Object.defineProperty() 第三个参数的配置项
好了,现在我们对 Object.defineProperty() 已经有了初步的了解,接下来我们对它的第三个参数的配置项进行深一层次了解:
// 我们对该对象来做详细的操作,后面不再声明
let obj = {
name: '张三',
gender: '男',
};
①、configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性
,默认值为false。
Object.defineProperty(obj, 'name', {
configurable: true, // 允许删除
});
console.log(obj); // =>{name:'张三',gender:'男'}
delete obj.name; // delete把name属性给删除掉了
console.log(obj); // =>{{gender: '男'}}
②、value:包含这个属性的数据值
,默认值为undefined。
Object.defineProperty(obj, 'age', {
value: 20,
});
console.log(obj); // =>{name:'张三',gender:'男',age:20}
obj.age = 24;
console.log(obj); // =>{name:'张三',gender:'男',age:20}
// 对象新加了一个age属性,并且只读的(无法修改属性值)
③、writable:表示能否修改属性的值
,默认值为false。 配置 writable 为 true后,属性值就可以修改了:
// 对象新加了一个age1 属性,并且可以修改值
Object.defineProperty(obj, 'age1', {
value: 22,
writable: true,
});
console.log(obj); // =>{name:'张三',gender:'男',age1:22}
obj.age1 = 21;
console.log(obj); // =>{name:'张三',gender:'男',age1:21}
④、enumerable:表示能否通过for···in循环访问属性
,默认值为false。为false时,for、Object.keys、JSON.stringify都打印不出来:
Object.defineProperty(obj, 'name', {
enumerable: false,
});
for (let i in obj) {
console.log(i); // => gender
}
console.log(Object.keys(obj)); // => ['gender']
console.log(JSON.stringify(obj)); // => {"gender":"男"}
当设置为true的时候对象的属性可被枚举
Object.defineProperty(obj, 'name', {
enumerable: true,
});
for (let i in obj) {
console.log(i); // => name gender
}
console.log(Object.keys(obj)); // => ['name', 'gender']
console.log(JSON.stringify(obj)); // => {"name":"张三","gender":"男"}
⑤、get:是获取值的时候的方法
,类型为 function ,获取值的时候会被调用,不设置时为undefined。
⑥、set:是设置值的时候的方法
,类型为 function ,设置值的时候会被调用,undefined。该方法接受一个参数,为修改后的值
Object.defineProperty(obj, 'name', {
get() {
console.log('name被访问');
},
set(v) {
console.log('name被修改为' + v);
},
});
obj.name; // get方法被调用,=> name被调用
obj.gender; // get方法没被调用
obj.name='李四'; // set方法被调用,=> 那么被修改为李四
我们对Object.defineProperty的第三个参数的配置已经有了了解,接下来我们将它的配置进行混合使用:
var student = {};
let pl = {};
Object.defineProperties(student, {
name: {
writable: false, // 不可修改
value: 'lisi', //默认值
},
age: {
writable: true, // 可修改
value: 16, //默认值
},
sex: {
get() {
return '男';
},
set(v) {
p1.sex = v;
},
},
});
p1.sex = '男';
console.log(student.name + ',' + student.age); // => lisi:16
console.log(student); // => {name: 'lisi', age: 16}
console.log(p1.sex); // 男
student.sex = '女';
console.log(student.sex); //男
console.log(p1.sex); // 女
2、js模拟v-model
相信大家已经对Object.defineProperty有了更进一步的认识,那么我们用JS模拟 v-model,详看代码:
<!--html-->
<input id="myInput" type="text" />
<div id="contain"></div>
//js
let text,
a = {},
ipt = document.getElementById('myInput'),
wp = document.getElementById('contain');
ipt.addEventListener('input', function (e) {
text = e.target.value; //获取触发事件的目标对象的值
console.log(text);
a.value = text;
});
Object.defineProperty(a, 'value', {
get() {
return '';
},
set(v) {
wp.innerHTML = v;
},
});
下面是效果,只是图片(不会发动图),凑合看吧…
初次发表文章,有哪里不对的还望大家指正,也希望此文章大家有所帮助。