function viewChange(type){
console.log('update view:'+type)
}
const originalProto=Array.prototype
//Object.create()创建一个新对象,原型指向originalProto,扩展新方法不会影响原型
const arrayProto=Object.create(originalProto)//克隆Array的原型
const methodsToPatch=['push','pop','shift','unshift','splice','sort','reverse']
methodsToPatch.map(item=>{
arrayProto[item]=function(){
originalProto[item].apply(this,arguments)
// originalProto[item].call(this,arguments)
// Array.prototype.push.call(this,arguments)
viewChange('array')
}
})
function objDefineProperty(obj,key,val){
arrObserver(val)
Object.defineProperty(obj,key,{
get(){
return val
},
set(newVal){
if(newVal!==val){
val=newVal
viewChange('object')
}
}
})
}
function arrObserver(arr){
if(typeof arr!=='object'||arr===null){
return arr
}
if(Array.isArray(arr)){
//Array.prototype.push=function(){...} 这么写会污染全局的Array原型
arr.__proto__=arrayProto
for(let i in arr){
arrObserver(arr[i])
}
}else{
for(let i in arr){
objDefineProperty(arr,i,arr[i])
}
}
}
const arr=['aaa','bbb','ccc',[111]]
arrObserver(arr)
arr[0]='ddd'
arr.push('ddd')
arr[3].push(222)
const obj={
name:'name',
child:{
name:'child name'
}
}
arrObserver(obj)
obj.name='name1'
obj.child.name='child name 1'
console.log(arr)
vue-响应式原理-Object.defineProperty监听数组和对象
于 2022-04-15 16:52:12 首次发布
该博客主要介绍了如何使用JavaScript实现对数组方法的拦截,通过`Object.create()`和`Object.defineProperty()`来监听数组的变化,从而触发特定的视图更新操作。同时,展示了如何递归地观察和定义对象属性,确保数据变化时能及时更新视图。
摘要由CSDN通过智能技术生成