Javascript Object Composition with assign & Object.creat

Javascript Object Composition with assign & Object.create

本文关键字:Object amp creat assign Composition with Javascript      更新时间:2023-09-26

试图使用分配来理解JavaScript组合。我的基对象上的属性意外地在实例之间共享。我做错了什么?我有。。。

统计.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;

生命值.js:

import assign from 'object-assign'
import Stat from './Stat.js';
var HitPoints = assign({}, Stat, {        
    getMax: function() {
        return 100;
    }
});
module.exports = HitPoints;

单位.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

感谢您的帮助...

首先,举一个快速的例子来说明为什么人们不希望你使用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? */
  }
}

在过去的30 +年中,class继承已被证明是人们严重滥用的东西之一(就像其他所有有用的工具一样)。

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

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());

我们想要的最终结果而言,变化不大......我们已经能够简化很多,现在我们甚至可以给他一个交换枪支的方法,如果我们愿意,这一切都是因为当我们第一次见到他时,我们不是把枪栓在他继承的东西上,而是递给他一把枪。它可以是我们想要的任何类型的枪,只要它仍然可以以类似的方式发射。

问题来了:那么,如果继承完全不在桌面上,是否有更好的方法来使事情可重用?

对此,我说:继承不应该完全不在桌面上......它应该离得很远,它应该是一个"啊哈"的时刻,当你发现这确实是完成某事的最好和最干净的方式(而不是试图继承.......什么东西,任何东西,现在!

各种语言都有一个称为特征或混合的概念。
在像Java这样的东西中,一个近似的近似是接口。
我不是接口的忠实粉丝(结构,而不是概念 - 喜欢这个概念)。
在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 的实例上。

现在,我可以根据需要创建任意数量的这些特征,并将它们复制到任意数量的对象上,并以这种方式重用。

嗯,这奏效了...

统计.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;
    }
}

生命值.js:

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

单位.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

这篇文章有所帮助。万岁!!!

不过,如果这从根本上是一种愚蠢的方式,请告诉我......