1.让属性不可枚举:
(function () { Object.defineProperty(ClassA.prototype, "propA", { get: propAGetter, set: propASetter, enumerable: false, configurable: false }); function checkPropA(self) { if (!(_propAName in self)) { if (!Object.isExtensible(self)) { throw new Error("can't define propA for nonextensible obj"); } Object.defineProperty(self, _propAName, { writable: true, value: _propA, enumerable: false, configurable: false }); } } function propASetter(v) { checkPropA(this); this[_propAName] += v; }; function propAGetter() { checkPropA(this); return this[_propAName]; }; var _propAName = "_propA"; var _propA = 1; })(); var b = new ClassB(1, 2, 3); for (var prop in b) { console.log(prop); } b.propA = 4; console.log(b.propA);
注意不是5,因为在B的构造函数中继承了ClassA的代码this.propA = paramA;
2.定义不可变的类:
定义一些工具函数:e.g.
//将制定名字或者所有的属性设置为不可写以及不可配置的 function freezeProps(o) { var props = (arquments.length == 1) ? Object.getOwnPropertyNames(o) : Array.prototype.splice.call(arguments,1); props.forEach(function(n) { if (!Object.getOwnPropertyDescriptor(o, n).configurable) return; Object.defineProperty(o, n, {writable: false, configurable: false}); }); return o; }
3.封装对象的状态:
将setter,getter函数更为严格地进行封装:
function setAndGetProp(o, p, g, s) { var obj = {enumerable: true, configurable: false}; if (g) obj.get = g; if (s) obj.set = s; Object.defineProperty(o, p, obj); }
//定义构造函数 function ClassA(paramA, paramB) { //定义实例字段 this.propA = paramA; function getParamB() { return paramB; }; function setParamB(value) { paramB = value; }; setAndGetProp(this, "paramB", getParamB, setParamB); }