一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情。
事故现场
是这样的,我在学习Object.defineProperties()方法的时候,給新设置的属性增添了get方法。
我的本意是当我给turkey实例的popularity属性设置值的时候,set方法会接收到这个属性值value,我就将属性值设置给popularity属性嘛,结果闯了大祸了
没想到一测试,就报了个内存溢出的错。
这是为什么捏?
发现在输出中出现了3000多行同一句话的输出,这肯定是循环调用了,且循环调用了set函数,说明我循环给popularity属性赋值了,所以问题就出现在了上图标红的那一行代码。
可见在set方法内部,是不能再给实例的当前属性赋值的,否则就会递归调用set函数,导致内存溢出。
改动这行代码,将value赋值给另一个属性(只要不是当前属性就可以)。
这时输出的就是:
>> 你认为turkey的受欢迎程度为5
本以为到这里就结束了,结果我又添加了一行代码,再次内存溢出了。😅
肯定又哪里写循环了,这次是get方法坏事了。
仔细看输出结果可以发现,这里压根没输出console.log(turkey.popularity)的结果。
当调用turke.popularity的时候,get方法自动回调,它会return this.popularity;,就在这里递归调用了,出了和刚才一样的问题。
可见get方法内部是不能调用当前属性的。
修改后的完整代码如下:
var turkey = {
brand: '白象',
price: 3,
};
Object.defineProperties(turkey,{
partner: {
value: '粉丝',
},
popularity: {
set: function(value){
console.log('你认为turkey的受欢迎程度为'+value);
this.price += value;
this.popularityScale = value;
},
get: function(){
return this.popularityScale;
}
},
});
turkey.popularity = 5;
console.log('白象火鸡面的受欢迎程度为:'+turkey.popularity);
这时输出结果就是正常的:
你认为turkey的受欢迎程度为5
白象火鸡面的受欢迎程度为:5
总结
这次问题在于对属性的两个方法: set和get的调用方式的不熟悉。
set方法是修改实例的当前属性时被调用的回调函数,它会用一个参数value接收修改的属性值。那么我们在set方法内部就不能再修改当前属性值了,不然会引发set方法的递归调用。
get方法是在获取实例时被调用的回调函数,同样的,在get方法内部不能获取当前属性值!