作者:yangchunwen
Object.observe 是一个提供数据监视的API,在 chrome 中已经可以使用。是 ECMAScript 7 的一个提案规范,官方建议的是“谨慎使用”级别,但是个人认为这个API非常有用,例如可以对现在流行的MVVM框架作一些简化和优化。虽然标准还没定,但是标准往往是滞后于实现的,只要是有用的东西,肯定会有越来越多的人去使用,越来越多的引擎会支持,最终促使标准的生成。
可以做什么
从observe字面意思就可以知道,这玩意儿就是用来做观察者模式之类的东东。
简单地说,就是观察一个对象的变化,在被观察者变化时作出一些回调。
实际应用中,可以优化数据模型(model)和网页试图(view)的双向绑定。
语法
语法很简单:
Object.observe(obj, callback)
obj
obj就是你要监听的数据模型(例如一个ajax接口对应的数据)
callback
callback就是数据模型变化后触发的回调(例如网页视图的变化)
callback函数的参数形式
- name: 被修改的属性名称
- object: 修改后该对象的值
- type: 表示对该对象做了何种类型的修改,可能的值为"add", "update", "delete", "reconfigure"
- oldValue: 对象修改前的值。该值只在"update"与"delete"有效
实例:
感兴趣可以跑一下下面简单的代码,你就知道各个参数的作用了
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script>
var obj = {};
Object.observe(obj, function (changes) {
changes.forEach(function (change) {
console.log('变化的属性: ' + change.name);
console.log('变化的类型?: ' + change.type);
console.log('旧值: ' + change.oldValue);
console.log('新值: ' + change.object[change.name]);
});
});
</script>
</body>
</html>
实现MVVM
当然这里不是要取代MVVM框架,只是想通过Object.observe来实现一些性能上的优化。
在Angular中有一个叫“脏值检查”的东西,大概的原理就是只要任何时候数据发生了变化,这个库都会通过一个digest或者change cycle去检查变化是否发生了。在Angular中,一个digest循环意味着所有所有被监视的表达式都会被循环一遍以便查看其中是否有变化发生。
用以下代码,大大优化了脏值检查
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>real MVVM</title>
</head>
<body>
<form id="person">
<input type="text" name="name" placeholder="名字">
<input type="text" name="age" placeholder="年龄">
</form>
<script>
var view = document.getElementById('person');
var infomation = {};
function bind(model, view) {
Object.observe(model, function (changes) {
changes.forEach(function (change) {
var property = change.name;
document.getElementsByName(property)[0].value = change.object[property];
});
});
Array.prototype.slice.call(view.getElementsByTagName('input')).forEach(function (input) {
input.addEventListener('input', function (e) {
var input = e.target;
if (input.tagName.toLowerCase() !== 'input') {
return;
}
var property = input.getAttribute('name');
model[property] = input.value;
});
});
}
bind(infomation, view);
</script>
</body>
</html>
脏值检查在任何数据可能发生变化的时候都必须要运行。这很明显并不是一个非常鲁棒的方法,并且任何实现脏值检查的途径都是有缺陷的(例如,在轮询中进行检查可能会造成视觉上的假象以及涉及到代码的紊乱情况)。脏值检查也需要注册一个全局的观察者,这很可能会造成内存泄漏,而Object.observe()会避免这一点。
参考
http://www.html5rocks.com/en/tutorials/es7/observe/