js社区最大的误解

介绍 (Introduction)

If you are trying to get a good understanding of what’s composition vs inheritance, you probably search on google etc., read articles and watch videos around “composition vs inheritance”. Here’s the problem, you are going to learn incorrect definition of composition.

如果您想很好地了解什么是组成与继承,则可以在Google等上搜索,阅读文章并观看有关“组成与继承”的视频。 这就是问题所在,您将学习错误的构图定义。

问题 (Problem)

This is coming from a book written in 1994.

这是1994年写的一本书。

“Favor object composition over class inheritance”

“类继承中的重要对象组成”

— Design Patterns: Elements of Reusable Object-Oriented Software (page 20)

—设计模式:可重用的面向对象软件的元素(第20页)

The majority of sources around “composition vs inheritance” has a huge misconception about the composition itself. But they use the statement above as a sign post, saying, hey, we should favor composition over inheritance. Actually this is one of the most misunderstood statements ever in the JS community. And the problem is not about the statement above, the statement itself is correct, the author gave a very strong argument why we should favor one over the other. The problem is that we have tons of beginners in JS community who get wrong mindset around composition, and tons of engineers who write weird code, thinking these authors were saying one thing, while in fact they meant something very different.

关于“合成与继承”的大多数资料都对合成本身有很大的误解。 但是他们使用上面的语句作为路标,说,嘿,我们应该更偏重于继承而不是继承。 实际上,这是JS社区中最容易被误解的语句之一。 问题不在于上面的陈述,陈述本身是正确的,作者提出了一个非常有力的论据,为什么我们应该偏爱一个。 问题是,JS社区中有成千上万的初学者对构图有错误的思维方式,有成千上万的工程师编写了怪异的代码,以为这些作者说的只是一件事,而实际上他们的意思却截然不同。

目标 (Goal)

There is an impression that everyone’s understanding of this word is just wrong. Our goal is to understand what’s the author talking about, and what composition actually is. The right way of composition vs inheritance. And finally, show what’s actually wrong with those explanations from different sources.

有一种印象,每个人对这个词的理解都是错误的。 我们的目标是了解作者在说什么,以及实际上是什么构成。 正确的组合与继承方式。 最后,说明不同来源的解释到底有什么问题。

好,让我们开始吧 (OK, let’s get into it)

—这本书的作者在说什么? (— What’s the book’s authors talking about?)

Delegation is a way of making powerful compositions. And that’s it, that’s what the author is saying. What’s actually “Delegation”? Well. Let me quote the author’s words. But before, let’s imagine we have a window which has a shape of rectangle, and has width, height, area.

委托是一种进行强有力的组合的方法。 就是这样,这就是作者所说的。 真正的“委派”是什么? 好。 让我引用作者的话。 但在此之前,让我们想象一下,我们有一个具有矩形形状,宽度,高度和面积的窗口。

“Instead of making class Window a subclass of Rectangle (because windows happen to be rectangular), the Window might reuse the behavior of Rectangle instance variable, and delegating Rectangle-specific behavior to it. In other words, instead of a Window being a Rectangle, it would have a Rectangle. Window must now forward request to its Rectangle instance explicitly, whereas before it would have inherited those operations.”

“代替将Window类作为Rectangle的子类(因为Windows恰好是矩形),Window可能会重用Rectangle实例变量的行为,并将Rectangle特定的行为委托给它。 换句话说,它不是矩形的窗口,而是矩形的。 现在,Window必须将请求显式转发到其Rectangle实例,而在此之前,它必须继承这些操作。”

— Same authors, same book and same page☝️

—同一作者,同一本书和同一页面 ☝️

真实构图 (Real Composition)

Let’s make two different javascript examples of this Window. In the first example Window uses inheritance, and in the second example Window reuses the behavior of Rectangle instance variable.

让我们为这个Window创建两个不同的javascript示例。 在第一个示例中, Window使用继承,在第二个示例中, Window重用Rectangle实例变量的行为。

class Rectangle {
    constructor(width, height) {
        this.width = width;
        this.height = height;
    }
    area() {
        return this.width * this.height;
    }
}


class Window extends Rectangle {
    constructor(width, height) {
        super(width, height);
    }
}


let rectangleWindow = new Window(3, 4)
class Rectangle {
    constructor(width, height) {
        this.width = width
        this.height = height
    }
    area() {
        return this.width * this.height
    }
}


class Window {
    constructor(shape) {
        this.shape = shape
    }
}


let rectangleShape = new Rectangle(3, 4)
let rectangleWindow = new Window(rectangleShape)

In the first one, we have a Window which “is” Rectangle. In the second one, instead of inheritance, the Windowhas” a Rectangle.

在第一个窗口中 ,我们有一个“ 是” Rectangle窗口 。 在第二个中, Window不是继承,而是“ 具有” Rectangle

The first example’s Window is less reusable being a Rectangle. Let’s imagine you have a Rounded class for rounded windows too. Well, you can’t extend both Rounded and Rectangle classes for the same Window class, and you can’t make an instance of Window for rounded windows either. But in the second example, Window can have an instance variable of Rounded class. Which makes the Window class much more reusable. Here’s how

第一个例子 窗口 不太可重用 矩形 假设您有一个 四舍五入 对于 四舍五入 窗户也一样。 好吧, 你不能同时扩展 四舍五入 长方形 对于相同的 窗口 无法 对圆窗 窗口 一个实例要么 但是在第二个示例中, Window可以具有Rounded类的实例变量。 这使得Window类具有更高的可重用性。 这是如何做

class Rectangle {
    constructor(width, height) {
        this.width = width
        this.height = height
    }
    area() {
        return this.width * this.height
    }
}


const pi = 3.14


class Rounded {
    constructor(radius) {
        this.radius = radius
    }
    area() {
        return this.radius**2 * pi
    }
}


class Window {
    constructor(shape) {
        this.shape = shape
    }
}


let rectangleShape = new Rectangle(3, 4)
let rectangleWindow = new Window(rectangleShape)


let roundedShape = new Rounded(5)
let roundedWindow = new Window(roundedShape)

—人们讨论构图时会做些什么 (— What people do when they discuss composition)

They return objects from their functions, and copy to another object using Object.assign (or spread operator). In the literal meaning, well, you can call it composition, but the thing is that you loose the object’s reference when you copy it.

他们从函数中返回对象,并使用Object.assign(或散布运算符)复制到另一个对象。 从字面意义上讲,您可以称其为composition,但事实是,在复制对象时,您会松开该对象的引用。

const rectangle = (width, height) => ({
    width,
    height,
    area: () => width * height,
})


const p = 3.14


const rounded = (r) => ({
    r,
    area: () => r ** 2 * p,
})


const makeRectangleWindow = (otherSpecificStuff, shape) => {
    return Object.assign(otherSpecificStuff, shape)
}


const makeRoundedWindow = (otherSpecificStuff, shape) => {
    return Object.assign(otherSpecificStuff, shape)
}


let rectangleWindow = makeRectangleWindow({ color: 'white' }, rectangle(3, 4))
let roundedWindow = makeRoundedWindow({ color: 'white' }, rounded(5))

So it’s a multiple inheritance, or a fake composition rather than that composition from the book “Design Patterns (1994)”.

因此,它是多重继承,或者是伪造的内容,而不是“ Design Patterns(1994)”一书中的内容。

结论 (Conclusion)

The book author’s composition is keeping the object’s reference by using instance variables. You might notice, there’s a huge difference between instance variables and object copies.

本书作者的构成是通过使用实例变量来保留对象的引用 。 您可能会注意到, 实例变量对象副本之间存在巨大差异。

I did my best to explain this in the simplest way, I hope it wasn’t too hard to understand even for a beginner. But if so, please, read again, play around the code, make your own one to understand better. Now that you have the right understanding of composition, open a google tab, do some research.

我尽力以最简单的方式解释了这一点,我希望即使对于初学者来说,也不难理解。 但是,如果是这样,请再次阅读,遍历代码,使自己的代码更好地理解。 既然您对构图有了正确的了解,请打开google标签,进行一些研究。

翻译自: https://medium.com/@jedavard/the-biggest-misconception-in-js-community-5545c15e932e

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值