Object.defineProperty()
给对象新增属性,或者设置对象的原有属性
Object.defineProperty(‘给那个对象新增属性’,‘新增的属性名叫啥’,{给新增的属性设置线管的配置项key:value})
value:配置项:给属性指定值
writable配置项:设置该属性是否可以修改 true/false
getter方法配置项:当读取属性值的时候该方法自动调用
getter方法的返回值就是你给这个属性设置的值
setter方法配置项:当属性值被修改的时候该方法自动调用
setter方法有一个参数,这个参数是可以接收传过来的值
注意:当配置项中有getter和setter的时候不能出现value和writable配置项
new Proxy()
两个参数 第一个 代理的哪一个对象,第二个一个对象包含函数就是给对象添加配置项
包含了数组的方法更加全面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="container"></div>
</body>
<script>
/* Object.defineProperty()
给对象新增属性,或者设置对象的原有属性
Object.defineProperty('给那个对象新增属性','新增的属性名叫啥',{给新增的属性设置线管的配置项key:value})
value:配置项:给属性指定值
writable配置项:设置该属性是否可以修改 true/false
enumerable配置项:该属性是否可以遍历 true/false
configurable配置项:该属性是否可以删除 true/false
getter方法配置项:当读取属性值的时候该方法自动调用
getter方法的返回值就是你给这个属性设置的值
setter方法配置项:当属性值被修改的时候该方法自动调用
setter方法有一个参数,这个参数是可以接收传过来的值
注意:当配置项中有getter和setter的时候不能出现value和writable配置项
*/
const phone = {};
let temp
Object.defineProperty(phone, "color", {
// value:'太空灰',
// writable:true,
//当读取对象中的属性值会调用 phone.color
get() {
console.log('getter方法调用了');
return temp
},
//当修改对象中的属性值时会调用 phone.color='red'
set(val) {
console.log('setter方法执行了', val);
temp = val
}
})
//编写一个对象,把对象的属性显示到页面上,再进行对对象的属性修改时页面跟随变化
const obj = {
name: '一号',
age: 18
}
const container = document.getElementById('container');
// console.log(container);
// textContent和innerHTML类似
//我们现在对obj.name修改发现修改后页面并不变化需要从新渲染
//obj.name = '二号'; //虽然数据变了,但是页面没有变化需要从新渲染
//container.textContent=obj.name; //从新渲染才可以
//第二种 使用代理Proxy
//我们使用代理就可以解决这个问题
//两个参数 第一个 代理的哪一个对象,第二个一个对象包含函数就是给对象添加配置项
const p1 = new Proxy(obj, {
get(target, property, receiver) {
// 数据对象 属性名 Proxy实例
//获取的时候
//obj[property] 就是获取对象中的所有属性
return obj[property]
},
set(target, property, value, receiver) {
// 数据对象 属性名 修改的值 Proxy实例
//修改的时候
obj[property] = value
container.textContent = obj.name;
}
})
console.log(p1.name);
p1.name = '三号'
// 双向数据绑定
const vm = {}
const target = {
name: '张三'
}
Object.defineProperty(vm, "name", {
getter() {
return target.name
},
setter(val) {
target.name = val
}
//这时候你去修改vm.name会影响target.name 你修改target.name会影响vm.name
})
// 对比下面的代码
// const target={
// name:'张三'
// }
// const vm=new Vue({
// el:'#app',
// data:target data:{name}===target.name
// })
//仿写vue中的双向数据绑定
class Vue {
// options就是一个js对象,对象内有一个data配置项
constructor(options) {
//获取对象中属性名为data的
Object.keys(options.data).forEach((propertyName, index) => {
console.log(propertyName, index);
//如果代理的元素第一个元素是$或_就不代理
let firstChar = propertyName.charAt(0)
if (firstChar != '_' && firstChar != '$') {
//这里用propertyName是因我们可能是给多个元素进行代理
Object.defineProperty(this, propertyName, {
get() {
//读取一个对象中的两种方式 obj.name || obj['name']
return options.data[propertyName]
},
set(val) {
options.data[propertyName] = val
}
})
}
})
//对methods中所有的函数进行代理
Object.keys(options.methods).forEach((methodsName,index)=>{
this[methodsName]=options.methods[methodsName]
})
}
}
</script>
</html>