提问者:小点点

JS中的合成


我正在学习JS中的作文概念。下面是我的演示代码。

moveby函数将值正确分配给xy

但是,setFillColor函数不将传递的值赋给FillColor

调用setfillcolor函数时到底发生了什么?

null

const withMoveBy = (shape) => ({
  moveBy: (diffX, diffY) => {
    shape.dimensions.x += diffX;
    shape.dimensions.y += diffY;
  },
});

const withSetFillColor = (shape) => ({
  setFillColor: (color) => {
    console.log(shape.fillColor);                      // 1
    shape.fillColor = color;
    shape.dimensions.fillColor = color;
    console.log(shape.fillColor);                      // 2
  },
});

const shapeRectangle = (dimensions) => ({
  type: 'rectangle',
  fillColor: 'white',
  dimensions,
});

const shapeCircle = (dimensions) => ({
  type: 'circle',
  fillColor: 'white',
  dimensions,
});

const createShape = (type, dimensions) => {
  let shape = null;
  switch (type) {
    case 'rectangle': {
      shape = shapeRectangle(dimensions);
      break;
    }
    case 'circle': {
      shape = shapeCircle(dimensions);
      break;
    }
  }

  if (shape) {
    shape = {
      ...shape,
      ...withSetFillColor(shape),
      ...withMoveBy(shape),
    };
  }
  return shape;
};

let r = createShape('rectangle', {
  x: 1,
  y: 1,
  width: 10,
  height: 10,
});

let c = createShape('circle', { x: 10, y: 10, diameter: 10 });

r.moveBy(2, 3);
c.moveBy(1, 2);

r.setFillColor('red');
c.setFillColor('blue');

console.log(r);
console.log(c);

null

输出:

对于矩形和圆形,标记为//1的行打印白色

标记为//2的行打印矩形的红色和圆形的蓝色

最终输出为:

{
  "type": "rectangle",
  "fillColor": "white",
  "dimensions": {
    "x": 3,
    "y": 4,
    "width": 10,
    "height": 10,
    "fillColor": "red"
  }
}
{
  "type": "circle",
  "fillColor": "white",
  "dimensions": {
    "x": 11,
    "y": 12,
    "diameter": 10,
    "fillColor": "blue"
  }
}

作为对象属性的FillColor仍然是White。但是,dimensions中的值是正确的。


共1个答案

匿名用户

问题源于createshape-me的注释中的分配:

    // creating the "new object"
    shape = {
      ...shape, // shallow copying of the "old object"
      ...withSetFillColor(shape),
      ...withMoveBy(shape),
    };

在这里,您创建了一个新对象,该对象由以下内容组成:

  • 浅层复制现有...Shape的属性(类型、填充颜色、作为对象的维度)
  • SetFillColor,绑定到Shape(旧对象)
  • 的闭包
  • moveby,绑定到shape(旧对象)
  • 的闭包

执行此语句后,您创建了两个形状:

  • 方法操作的“旧对象”
  • 返回的“新对象”

在从旧对象复制的属性中,只有dimensions是一个非原语值,因此它在实例之间共享。

然后,当你打电话:

r.moveBy(2, 3);

它更改了oldshape.dimensions,但它与newshape.dimensions是同一个对象,因此在输出中可见。

然而,这一呼吁:

r.setFillColor('red');

修改OldShapeFillColor属性,您没有看到该属性。它还写入oldshape.dimensions.fillcolor,该文件同样在对象之间共享,因此更改在两个对象中都可见。