类似vue2中数据劫持的简单实现
const callBack = (newval, oldval) => {
console.log(newval, oldval)
}
const OP = Object.prototype;
const types = {
obj: '[object Object]',
array: '[object Array]'
}
const OAM = ['push', 'pop', 'shift', 'unshift', 'short', 'reverse', 'splice']
export default class Jsonob {
constructor(obj, cb = callBack) {
if (OP.toString.call(obj) !== types.obj && OP.toString.call(obj) !== types.array) {
console.log('请传入一个对象或数组');
return false;
}
this._callback = cb;
this.observe(obj);
}
observe(obj, path) {
if (OP.toString.call(obj) === types.array) {
this.overrideArrayProto(obj, path);
}
Object.keys(obj).forEach((key) => {
let oldVal = obj[key];
let pathArray = path && path.slice();
if (pathArray) {
pathArray.push(key);
} else {
pathArray = [key];
}
Object.defineProperty(obj, key, {
get: function() {
return oldVal;
},
set: (function(newVal) {
if (oldVal !== newVal) {
if (OP.toString.call(newVal) === '[object Object]') {
this.observe(newVal, pathArray);
}
this._callback(newVal, oldVal, pathArray)
oldVal = newVal
}
}).bind(this)
})
if (OP.toString.call(obj[key]) === types.obj || OP.toString.call(obj[key]) === types.array) {
this.observe(obj[key], pathArray)
}
}, this)
}
overrideArrayProto(array, path) {
var originalProto = Array.prototype,
overrideProto = Object.create(Array.prototype),
self = this,
result;
OAM.forEach((method) => {
Object.defineProperty(overrideProto, method, {
value: function() {
var oldVal = this.slice();
result = originalProto[method].apply(this, arguments);
self.observe(this, path);
self._callback(this, oldVal, path);
return result;
}
})
});
array.__proto__ = overrideProto;
}
let arr = [1, 2, 3, 4]
let newarr = new Jsonob(arr, () => {
console.log('running in trigger')
})
newarr.push('5')
查看原文