JS对象组成

时间:2017-07-06 16:43:48

标签: javascript class oop prototype composition

我有2个对象形状尺寸

var Size = function(opts = {}) {
   this.width = opts.width || 0;
   this.height = opts.height || 0;
}

Size.prototype.get = function() {
   return {
      height: this.height, 
      width: this.width
   }
}

Size.prototype.setHeight = function(h) { 
   this.height = h; 
}

Size.prototype.setWidth = function(w) { 
   this.width = w; 
}

var Shape = function(opts = {}) {
  this.size = new Size(opts.size);
}

我想为我的Shape Object实现一个函数 getSize 。但我不知道如何处理这个功能。

第一个选项是返回大小数据(普通对象),如下所示:

// First implementation
Shape.prototype.getSize = function() {
   return this.size.get();   
}
shape.getSize() // {height: 0, width: 0}

第二个选项是返回Object上下文的大小:

// Second implementation
Shape.prototype.getSize = function() {
   return this.size;
}
shape.getSize(); // Size {height: 0, width: 0}` 
shape.getSize().setHeight(5); // I can now manage the size context 
shape.getSize().get();` //{height: 0, width: 0}

有会议吗?还是更具灵活性和可组合性的东西?

1 个答案:

答案 0 :(得分:1)

应该考虑@Bergi和@FelixKling已经建议的所有内容......

  

刚刚返回属性的getter非常无用。没有理由不写shape.size.get()...

...

  

为什么甚至有Size.prototype.get?为什么要写size.get()。width而不是size.width?

从OP的代码中可以看出,我想到了以下想法......

  • 对于使用选项/配置对象Size的{​​{1}}和返回另一个opts对象的getter方法...为什么不总是直接在本地操作范围opts州?
  • 至于options的高级默认值赋值...为什么不完全使用类语法,继承组合。

灵活的解决方案可能看起来像下面的示例代码......

opts

class EncapsulatedValue {
    constructor(options = {}) {
        function valueOf() {
            return Object.assign({}, options);
        }
        function toString() {
            return JSON.stringify(options);
        }
        this.valueOf = valueOf;
        this.toString = toString;
    }
}

class Size extends EncapsulatedValue {
    constructor(options = {}) {
        function setWidth(value) {
            return (options.width = value);
        }
        function setHeight(value) {
            return (options.height = value);
        }
        function getWidth() {
            return options.width;
        }
        function getHeight() {
            return options.height;
        }
        options.width = options.width || 0;
        options.height = options.height || 0;

        super(options);

        Object.defineProperty(this, 'width', {
            set: setWidth,
            get: getWidth,
            enumerable: true
        });
        Object.defineProperty(this, 'height', {
            set: setHeight,
            get: getHeight,
            enumerable: true
        });
    }
}

class Shape extends EncapsulatedValue {
    constructor(options = {}) {
        function getSize() {
            return options.size;
        }
        options.size = new Size(options.size);

        super(options);

        Object.defineProperty(this, 'size', {
            get: getSize,
            enumerable: true
        });
    }
    getSizeValue() { // implementation even can be omitted.
        return this.size.valueOf();
    }
}

var shape = (new Shape);

console.log('shape : ', shape);
console.log('shape.size : ', shape.size);

console.log('(shape + "") : ', (shape + ""));
console.log('shape.valueOf() : ', shape.valueOf());

console.log('(shape.size + "") : ', (shape.size + ""));
console.log('shape.size.valueOf() : ', shape.size.valueOf());

console.log('shape.getSizeValue() : ', shape.getSizeValue());

console.log('JSON.stringify(shape) : ', JSON.stringify(shape));
console.log('JSON.stringify(shape.size) : ', JSON.stringify(shape.size));

console.log('(shape instanceof Shape) ? ', (shape instanceof Shape));
console.log('(shape instanceof EncapsulatedValue) ? ', (shape instanceof EncapsulatedValue));

console.log('(shape.size instanceof Size) ? ', (shape.size instanceof Size));
console.log('(shape.size instanceof EncapsulatedValue) ? ', (shape.size instanceof EncapsulatedValue));

console.log('shape.hasOwnProperty("size") ? ', shape.hasOwnProperty("size"));
console.log('shape.hasOwnProperty("getSizeValue") ? ', shape.hasOwnProperty("getSizeValue"));