传说

大名鼎鼎的vue.js是通过它实现双向绑定的。俗称属性拦截器。而且专门用来监控对象属性变化的Object.observe方法也被草案发起人撤回了(此方法在node环境中仍能使用)。可见defineProperty的威力之大了。

作用

在创建普通属性时属性描述符会使用默认值, 我们也可以使用 Object.defineProperty(..)
来添加一个新属性或者修改一个已有属性(如果它是 configurable) 并对特性进行设置。

栗子

这里暂且不讨论vue.js双向绑定的实现原理,而是使用for of遍历对象属性的值。

var myObject = {
a: 2,
b: 3
};
Object.defineProperty( myObject, Symbol.iterator, {
enumerable: false,
writable: false,
configurable: true,
value: function() {
var o = this;
var idx = 0;
var ks = Object.keys( o );
return {
next: function() {
return {
value: o[ks[idx++]],
done: (idx > ks.length)
};
}
};
}
} );
// 手动遍历 myObject
var it = myObject[Symbol.iterator]();
it.next(); // { value:2, done:false }
it.next(); // { value:3, done:false }
it.next(); // { value:undefned, done:true }
// 用 for..of 遍历 myObject
for (var v of myObject) {
console.log( v );
}

我们使用 Object.defineProperty(..) 定义了我们自己的 @@iterator(主要是
为了让它不可枚举), 不过注意, 我们把符号当作可计算属性名(本章之前
有介绍)。 此外, 也可以直接在定义对象时进行声明, 比如 var myObject = {
a:2, b:3, [Symbol.iterator]: function() { /* .. */ } }。
for..of 循环每次调用 myObject 迭代器对象的 next() 方法时, 内部的指针都会向前移动并
返回对象属性列表的下一个值(再次提醒, 需要注意遍历对象属性 / 值时的顺序)。