【前端的坑】不知不觉就递归调用了😅

784 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

事故现场

是这样的,我在学习Object.defineProperties()方法的时候,給新设置的属性增添了get方法。

我的本意是当我给turkey实例的popularity属性设置值的时候,set方法会接收到这个属性值value,我就将属性值设置给popularity属性嘛,结果闯了大祸了

image.png

没想到一测试,就报了个内存溢出的错。

image.png

这是为什么捏?

发现在输出中出现了3000多行同一句话的输出,这肯定是循环调用了,且循环调用了set函数,说明我循环给popularity属性赋值了,所以问题就出现在了上图标红的那一行代码。

可见在set方法内部,是不能再给实例的当前属性赋值的,否则就会递归调用set函数,导致内存溢出。

改动这行代码,将value赋值给另一个属性(只要不是当前属性就可以)。

image.png

这时输出的就是:

>> 你认为turkey的受欢迎程度为5

本以为到这里就结束了,结果我又添加了一行代码,再次内存溢出了。😅

image.png

肯定又哪里写循环了,这次是get方法坏事了。

image.png

仔细看输出结果可以发现,这里压根没输出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方法内部不能获取当前属性值!