起步

// 数据对象
class appData {
    // 构造函数
    constructor(rawGoods) {
        this.goods = [];
        rawGoods.forEach(element => {
            this.goods.push(new good(element));
        });
    }

    // 函数
    getTotal(){
    	return 0;
    }
}

// UI对象、dom对象
class ui{
    constructor(){
        this.uiData = new appData();
        this.doms = {
            goodsList: document.getElementById("goodsList"),
        }
        this.createHTML();
    }

    createHTML(){
        // do something
    }
}


属性描述符

用于增加程序的健壮性

class good {
    constructor(rawData) {
        // 克隆数据,原始数据可能改动
        const rawDataClone = { ...rawData };
        // 冻结属性,属性和其内容都不能改
        Object.freeze(rawDataClone);
        // 只读属性
        Object.defineProperties(this, 'rawData', {
            get: function () {
                return rawDataClone;
            },
            set: function (value) {
                throw new Error('rawData is readonly');
            },
        });
        let internalNumber = 0;
        Object.defineProperties(this, 'number', {
            get: function () {
                return internalNumber;
            },
            set: function (value) {
                // 是否是数字
                if(typeof value != 'number')
                    throw new Error('number shold be a number');
                // 是否是整数
                if(value != Math.floor(value))
                    throw new Error('number shold be a integer');
                // 是否是非负数
                if (value < 0)
                    throw new Error('number shold be a positive number');
                internalNumber = value;
            }
        });
        // 密封属性,初始化后不能改动内容
        Object.seal(this);
        // 冻结原型,不准在原型上加东西
        Object.freeze(this.prototype);
    }
}

获取属性描述符

Object.getOwnPropertyDescriptor(app, 'goods')

设置属性描述符

Object.defineProperties(obj, 'a', {
    configurable: true, // 属性符能否再次修改
    enumerable: true, // 可枚举(打印、for of)
    value:  [good, good, good], // 值
    writable: true, // 值能否修改
    get: function () {},
    set: function () {},
})

冻结对象

冻结属性,属性和其内容都不能改

class good {
    constructor(rawData) {
        // 冻结属性,属性和其内容都不能改
        Object.freeze(rawData);
        // 冻结原型
        Object.freeze(this.prototype);
    }
}

密封

不能加属性,但是已有属性值可以改

class good {
    constructor(rawData) {
        // 不能加属性,但是已有属性值可以改
        Object.seal(this);
    }
}