Skip to content

Instantly share code, notes, and snippets.

@YingshanDeng
Last active March 3, 2017 13:34
Show Gist options
  • Save YingshanDeng/9caa1da5784a19024ca8427b1ae1bf8e to your computer and use it in GitHub Desktop.
Save YingshanDeng/9caa1da5784a19024ca8427b1ae1bf8e to your computer and use it in GitHub Desktop.
<html>
<head>
<meta charset="UTF-8">
<title>object-observe</title>
<style>
</style>
</head>
<body>
<script>
function Observer (obj, callback) {
var observe = function (obj, path) {
let type = Object.prototype.toString.call(obj);
if(type === '[object Object]' || type== '[object Array]') {
observeObject(obj, path);
if (type === '[object Array]') {
observeArrayPreparation(obj, path);
}
}
}
var observeObject = function (obj, path) {
// for...in 可以遍历对象的实例属性和原型属性,而 Object.keys 只遍历实例属性
for (let prop in obj) {
// 注意:不能用 var
let value = obj[prop],
_path = path.slice(); // 主要对 path 数组进行一次拷贝
_path.push(prop); // 记录路径
Object.defineProperty(obj, prop, {
set: function(newVle) {
callback(_path, newVle, value);
value = newVle;
},
get: function() {
return value;
}
});
// 递归
observe(value, _path);
}
}
var observeArrayPreparation = function (arr, path) {
var _props = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];
var _newProto = Object.create(Array.prototype);
_props.forEach((prop) => {
Object.defineProperty(_newProto, prop, {
value: function () { // 注意:数组方法的参数个数不确定,所以此处暂不处理
var _path = path.slice();
_path.push(prop);
// 注意:此处只返回 path
callback(_path);
Array.prototype[prop].apply(arr, arguments);
}
})
});
arr.__proto__ = _newProto;
}
observe(obj, []);
}
var obj = {
a: 1,
b: 2,
c: [3, 4]
};
new Observer(obj, (path, newVle, oldVle) => {
console.log(`path: ${path}, newValue: ${newVle}, oldValue: ${oldVle}`)
})
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment