Javascript对象组合与assign&的Object.create

时间:2016-03-21 03:00:45

标签: javascript object composition assign

尝试使用assign围绕javascript组合。我的基础对象上的属性意外地在实例之间共享。我究竟做错了什么?我有......

Stat.js:

import assign from 'object-assign';
var Stat = assign({}, {
    _value: undefined,

    get: function() {
        return this._value;
    },

    set: function(n) { 
        var max = this.getMax();

        if(n > max) {
            this._value = max;
        } else {
            this._value = n; 
        }
    },

    getMax: function() {
        return 1;
    }
});
module.exports = Stat;

HitPoints.js:

import assign from 'object-assign'
import Stat from './Stat.js';

var HitPoints = assign({}, Stat, {        
    getMax: function() {
        return 100;
    }
});
module.exports = HitPoints;

Unit.js:

import assign from 'object-assign';
import HitPoints from 'HitPoints.js';

var Unit = assign({}, {
        hp: Object.create(HitPoints)
    }
);
module.exports = Unit; 

用法:

import Unit from 'Unit.js';

var u1 = Object.create(Unit);
console.log( u1.hp.get() ); // undefined - ok
u1.hp.set(11);
console.log( u1.hp.get() ); // 11 - ok

var u2 = Object.create(Unit);
console.log( u2.hp.get() ); // 11 - ???
u2.hp.set(22);
console.log( u1.hp.get() ); // 22 - ???
console.log( u2.hp.get() ); // 22

感谢您的帮助......

2 个答案:

答案 0 :(得分:6)

首先,快速举例说明人们不希望您使用class的原因 我并不一定讨厌class,但使用class的原因有90%是为了获得继承,虽然偶尔会有所帮助,但它往往会非常痛苦。

class Person { }


class ArmedPerson extends Person {
  constructor (details) {
    super(details);
    const gun = new Gun();
    this.equipment = { gun };
  }

  attack (target) {
    this.equipment.gun.fireAt(target);
  }
}


class Civilian extends Person { }


class ArmedCivilian extends ArmedPerson {
  /* ... shouldn't it be extending Civilian?
    Maybe all Civilians should be armed?
    Is this why most games take place in the US?
  */
}


class Soldier extends ArmedPerson {
  constructor (personDetails) {
    super(personDetails);
  }
}


class UnarmedSoldier extends Soldier {
  /* HOW DO I TAKE HIS GUN AWAY? */
  constructor (personDetails) {
    super(personDetails);
  }
  attack () {
    /* I know he has a gun, and anybody hacking the game can use it, but what do I do here? */
  }
}

class继承已经证明是过去30多年来人们滥用的事情之一(就像其他所有有用的工具一样)。

我们可以查看组合(通过依赖性反转)而不是继承。

class Soldier {
  constructor (personDetails, gun) {
    /*...setup...*/
    this.equipment = { gun };
    this.selectedWeapon = gun;
  }

  attack (target) {
    this.selectedWeapon.fireAt(target);
  }
}


const soldier = new Soldier({ /*...details... */ }, new Gun());

就我们想要的最终结果而言,并没有太多变化......我们已经能够真正简化了很多,现在我们甚至可以给他一个方法来交换枪,如果我们想要,所有因为而不是把枪闩成他继承的东西,我们在第一次见到他时给他递了一把枪。 它可以是我们想要的任何类型的枪,只要它仍然可以以类似的方式发射。

问题出现了: 那么,如果继承完全不在桌面上,那么有更好的方法可以重复使用吗?

对于我说:继承不应该完全脱离桌面......当你发现它确实是真的时候它应该只是偏离它应该是一个“啊哈”的时刻。完成某事的最好和最干净的方式(而不是试图继承.......某事,任何东西,现在!)。

各种语言都有一个称为Traits或Mix-Ins的概念 在类似Java的东西中,近似接近是接口 我不是Interfaces的忠实粉丝(结构,而不是概念 - 喜欢这个概念) 在Java中,接口使您可以完成更多工作,因为它们可以定义函数,函数采用的内容,返回的内容...... ...但你不能给它任何默认行为(传统上),所以如果你有14个对象实现相同的接口,那就是你写出14次的相同方法(加上接口的签名)。有时,这些方法在实施细节上会完全不同;这很好......有时候,它们会与您在编写界面时的预期完全相同。

那不太好。队列特征;这些是您定义界面,定义行为,然后复制到对象上的东西。 在JS中,我们甚至可以通过注入他们可以使用的上下文来获得一些封闭安全性,而不是让他们假设他们混淆了整个this

const Movable = (pos) => ({
  up (distance) { pos.y += distance; },
  down (distance) { pos.y -= distance; },
  left (distance) { pos.x -= distance; },
  right (distance) { pos.x += distance; }
});


class Point {
  constructor (x, y) {
    Object.assign(this, { x, y });
  }
}

class Person {
  constructor (position) {
    Object.assign(this, { position }, Movable(position));
  }
}


const person = new Person( new Point(0, 0) );

person.up( 20 );
person.position.y; // 20

如果你注意到,Movable正在返回一个对象的新实例,其方法可以改变position上的值。该对象将其方法复制到person的实例上。

我现在可以创建尽可能多的Traits,并将它们复制到我想要的任意数量的对象上,然后以这种方式重用。

答案 1 :(得分:-1)

嗯,这很有用......

Stat.js:

var Stat = {
    get: function() {
        return this._value;
    },

    set: function(n) { 
        var max = this.getMax();

        if(n > max) {
            this._value = max;
        } else {
            this._value = n; 
        }
    },

    getMax: function() {
        return 1;
    }
}

HitPoints.js:

var HitPoints = function() {
    return assign(Object.create(Stat), {    
        getMax: function() {
            return 100;
        }
    });
}

Unit.js:

var Unit = function() {
    return assign({},
        Object.create(XYPiece),
        Object.create(TeamMember),
        {
             hp: HitPoints()     
        }
    );                       
}

用法:

var u1 = Unit();
console.log( u1.hp.get() ); // undefined
u1.hp.set(11);
console.log( u1.hp.get() ); // 11

var u2 = Unit();
console.log( u2.hp.get() ); // undefined
u2.hp.set(22);
console.log( u1.hp.get() ); // 11
console.log( u2.hp.get() ); // 22

This文章有所帮助。万岁!!!

但是,如果这基本上是一种愚蠢的方式,请告诉我......