使用getter返回只读的嵌套对象

问题描述

我有一个愚蠢的问题,但找不到合适的解决方案。

想象一个具有嵌套私有属性的对象(用于滑块)-用于自动滚动的对象:

let slider = {
    slides: ...,arrows: ...,someMethods(),_autoScroll: {
        on: true/false,delay: in ms,run(),stop(),somethingElse...
    }
}

我定义了一个getter / setter,例如:

Object.defineProperty(slider,'autoScroll',{
        get() {
            return this._autoScroll; (****)
        },set(value) {
            if (value.on !== 'undefined') this._autoScroll.on = !!value.on;
            let a = Number(value.delay);
            if ( isFinite(a) && !isNaN(a) ) this._autoScroll.delay = a;
        }
    });

如您所见,我想有机会像下面这样设置.on和.delay属性

slider.autoScroll = {on:true,delay:2000};

问题在于,在(****)行中,我可以获得原始的嵌套对象_autoScroll,但是我也可以更改其属性,甚至添加一些新的!!!!!!

slider.autoScroll.on = 'some Crap';
slider.autoScroll.newProperty = 111;

它将更改原始对象。我希望看到一个完整的对象,但只读,没有这些东西。

一个可能的想法是在getter中使用JSON.stringify,但这与我想要的不一样。我考虑过的另一个选择是返回一个克隆对象,如

Object.defineProperties({},Object.getownPropertyDescriptors(obj));

或仅Object.assign()。但这太重了,没有必要,效果不好!

您认为,是否有任何方法或算法可以有效,快速,美观地完成此任务?最佳做法是什么?也许我根本不应该显示具有其所有属性的整个对象,而是某种反模式?我需要您的经验和建议

谢谢。

解决方法

使用您提到的Object.assign方法对我来说很简洁:

return Object.assign({},this._autoScroll);

您可以通过传播更加简洁地做到这一点:

return { ...this._autoScroll };

请注意,如果对象属性发生更改,.autoScroll的调用者将不得不再次调用它以获取更新的对象数据。