vue源码中对闭包的使用

68 阅读1分钟

数据响应化Observer中使用闭包

// 注:由于Vue源码中有大量与闭包不相关的代码可能会影响阅读和理解,
// 故此处不照抄Vue源码,而是本人根据Vue源码的实现原理实现的简易版响应式代码,方便阅读与理解
function defineRealive(target, key, value){
	return Object.defineProperty(target, key, {
		get(){
			console.log(`通过getter获取数据:${value}`);
			return value;
		},
		set(val){
			console.log(`通过setter设置数据:新值-${val};旧值-${value}`);
			// 很多人会疑问,value明明是形参,为什么给他赋值就能够达到数值改变的效果呢?形参不是出了这个函数就没用了么?
			// 其实,这就用到了闭包的原理,value是外层函数defineRealive的参数,而我们实际上使用value确是在内层的get或set方法里面
			// 这样就形成了一个闭包的结构了。根据闭包的特性,内层函数可以引用外层函数的变量,并且当内层保持引用关系时外层函数的这个变量
			// 不会被垃圾回收机制回收。那么,我们在设置值的时候,把val保存在value变量当中,然后get的时候再通过value去获取,这样,我们再访问
			// obj.name时,无论是设置值还是获取值,实际上都是对value这个形参进行操作的。
			value = val;
		}
	});
}
 
let obj = {
	name: 'kiner',
	age: 20
};
 
Object.keys(obj).forEach(key=>defineRealive(obj, key, obj[key]));
 
obj.name = 'kanger';// 控制台输出:通过setter设置数据:新值-kanger;旧值-kiner
obj.age = 18;// 控制台输出:通过setter设置数据:新值-18;旧值-20
 
 
// 控制台输出:通过getter获取数据:kanger
// 控制台输出:通过getter获取数据:18
// 控制台输出:kanger 18
console.log(obj.name,obj.age);