css 原型图片_使用CSS解释JavaScript的原型继承

css 原型图片

by Nash Vail

由Nash Vail

使用CSS解释JavaScript的原型继承 (JavaScript’s Prototypal Inheritance Explained Using CSS)

Prototypal inheritance is arguably the least understood aspect of JavaScript. Well the good news is that if you understand how CSS works, you can also understand how JavaScript prototypes work.

原型继承可以说是JavaScript最少了解的方面。 好消息是,如果您了解CSS的工作原理,那么您也可以了解JavaScript原型的工作原理。

It’s beautiful when something simple is able to explain something seemingly complex, an analogy — like a piledriver drives a pole deep into the ground, an analogy drives the point home.

当简单的事物能够解释看似复杂的事物时,就很美,就像一个比喻-例如打桩机将一根杆子推入地面深处,一个比喻将要点指向家。

I am a lover of analogies, an analogyphile.

我是一个类比爱好者,一个类比爱好者。

Here we go.

开始了。

CSS按钮中的原型 (Prototypes in CSS Buttons)

See the two buttons above? We’re going to design them in CSS.

看到上面的两个按钮? 我们将使用CSS设计它们。

Let’s go ahead and quickly write styles for these two buttons, starting with .btn

让我们继续快速编写这两个按钮的样式,以.btn

.btn { min-width: 135px; min-height: 45px; font-family: ‘Avenir Next’, sans-serif; font-size: 18px; font-weight: bold; letter-spacing: 1.3px; color: #4D815B; background-color: #FFF; border: 2px solid #4D815B; border-radius: 4px;  padding: 5px 20px; cursor: pointer;}

That’s a reasonably simple block of CSS code.

那是一个相当简单CSS代码块。

Now let’s move to the styles for .btn-solid

现在让我们转到.btn-solid的样式

.btn-solid { min-width: 135px; min-height: 45px; font-family: ‘Avenir Next’, sans-serif; font-size: 18px; font-weight: bold; letter-spacing: 1.3px; color: #FFF; background-color: #4D815B; border: 2px solid #4D815B; border-radius: 4px;  padding: 5px 20px; cursor: pointer;}

As you might have already noticed, other than the bold ones, all the other styles in .btn-solid are identical to that of .btn. And If you are familiar with Sass, you may know that .btn-solid styles can be rewritten in SASS like so:

您可能已经注意到,除了粗体以外, .btn-solid中的所有其他样式都与.btn相同。 而且,如果您熟悉Sass ,您可能会知道.btn-solid样式可以用SASS重写,如下所示:

.btn-solid { @extend .btn; color: #FFF; background-color: #4D815B;}

As you can see, .btn-solid inherits styles from .btn, then overrides some of them (font and background color) to create itself. Which leads us to the conclusion that .btn-solid is a specialized version of .btn. Or, in other words, .btn-solid is .btn but with different font and background colors. That makes sense right? But wait there’s more.

如您所见, .btn-solid.btn继承样式,然后覆盖其中的某些样式(字体和背景颜色)以创建自身。 这导致我们得出以下结论: .btn-solid .btn的专用版本 换句话说, .btn-solid.btn但是具有不同的字体和背景颜色。 这样说对吗? 但是,等等。

Let’s say we want to create a larger button, .btn-lg. We’ll use .btn as a prototype to supply base styles. Then, similar to how we modified background and font colors to create .btn-solid, we’ll modify the font-size property to a larger value to create a larger button.

假设我们要创建一个更大的按钮.btn-lg 。 我们将使用.btn作为提供基本样式的原型 。 然后,类似于我们修改背景和字体颜色以创建.btn-solid ,我们将font-size属性修改为更大的值以创建更大的按钮。

Both .btn-lg and .btn-solid are specialized versions of .btn. .btn supplies base styles to .btn-lg and .btn-solid which then overwrite some of the base styles to create themselves. This tells us that a single button that we decide — .btn in our case — can be used as a supplier of base styles to multiple items.

无论.btn-lg.btn-solid专门的版本.btn.btn.btn-lg.btn-solid提供基础样式,然后覆盖一些基础样式以创建自己。 这告诉我们,我们确定的单个按钮(在我们的情况下为.btn可以用作多个项目的基本样式的提供者。

In this section, we tried to define the concept of prototypes for CSS buttons. A Prototype is an entity that supplies base styles, which can be extended to create different instances of buttons. This definition of a prototype is very close to what prototypes actually mean in programming terms.

在本节中,我们尝试定义CSS按钮原型的概念。 原型是提供基本样式的实体,可以将其扩展以创建按钮的不同实例。 原型的定义非常接近原型在编程方面的实际含义。

In programming terms, a prototype is an object that supplies base behavior to a second object. The second object then extends this base behavior to form its own specialization. Let’s see in the next section how our knowledge of prototypes in CSS buttons maps to JavaScript.

用编程术语来说,原型是为第二个对象提供基本行为的对象。 然后,第二个对象扩展此基本行为以形成其自己的专业化。 在下一部分中,让我们看看我们在CSS按钮中的原型知识如何映射到JavaScript。

JavaScript中的原型 (Prototypes in JavaScript)

Consider the following JavaScript object:

考虑以下JavaScript对象:

let obj = { a: 1};

We know that the value of a can be accessed by obj.a, given that a is clearly a property of obj. But there’s more, you can also call obj.hasOwnProperty('a') to check if obj actually has a property named a.

我们知道obj.a可以访问a的值,因为a显然是obj的属性。 但是还有更多,您还可以调用obj.hasOwnProperty('a')来检查obj实际上具有名为a属性。

Now wait a second — from what we can see, obj has no property called hasOwnProperty defined on it. Where did hasOwnProperty come from? To answer this question we’ll have to go back to the buttons we just finished creating.

现在,等待一秒钟-从我们的观察中可以看出, obj没有定义名为hasOwnProperty属性。 hasOwnProperty来自哪里? 要回答这个问题,我们必须回到刚刚完成的按钮。

.btn-solid just has background and font colors defined on it. Where is it getting, for example, border-radius from? We know that .btn-solid is a specialization of .btn, so we can see that .btn-solid is getting styles like border-radius, width, height, and padding from .btn. Could it be the same with obj?

.btn-solid只是具有定义的背景和字体颜色。 它从何处获得border-radius ? 我们知道.btn-solid.btn-solid一种特殊.btn ,因此我们可以看到.btn-solid.btn获得了border-radiuswidthheightpadding .btn 。 可以和obj吗?

Just like .btn-solid and .btn-lg get their base styles from .btn, obj or any other JavaScript object for that matter receive their base behavior from another object — Object.prototype. And this Object.prototype has hasOwnProperty defined on it. And as a result, this gives obj access to the hasOwnProperty method — just like .btn-solid had access to .btn's border-radius property.

就像.btn-solid.btn-lg.btnobj或任何其他JavaScript对象获取其基本样式.btn ,从另一对象 Object.prototype接收其基本行为。 并且此Object.prototype拥有hasOwnProperty定义。 结果,这使obj可以访问hasOwnProperty方法-就像.btn-solid可以访问.btnborder-radius属性一样。

This — an object (obj) inheriting its properties and base-behavior from another object (Object.prototype) — is what we call prototypal inheritance. Notice that there is no class involved in the interplay.

这就是一个对象 (obj) 从另一个对象 (Object.prototype) 继承其属性和基本行为的方式,我们称之为原型继承。 请注意,交互中不涉及任何class

The actual inner workings of JavaScript prototypes and our CSS “prototypes” are way different. But for the purpose of our analogy, we can ignore how they work behind the scenes.

JavaScript原型和CSS“原型”的实际内部运作方式截然不同。 但是出于类推的目的,我们可以忽略它们在后台的工作方式。

Object.prototype isn’t the only prototype available in JavaScript. There’s Array.prototype, Function.prototype, Number.prototype and several others. The job of all these prototypes is to supply base behavior or utility methods to their instances.

Object.prototype不是JavaScript中可用的唯一原型。 有Array.prototypeFunction.prototypeNumber.prototype等。 所有这些原型的工作是为其实例提供基本行为或实用程序方法。

For example every array declared in JavaScript has access to .push, .sort, .forEach, and .map only because of the prototypal linkage. And for the same reason every function has access to .call, .apply, .bind.

例如,JavaScript中声明的每个数组仅由于原型链接而可以访问.push.sort.forEach.map 。 出于同样的原因,所有的功能访问.call.apply.bind

Prototypes and prototypal inheritance aren’t JavaScript specific. They’re a construct that JavaScript uses internally that allows us to use it in our own programs. Before we look at how exactly we can do that, we need to understand what prototypal chaining is.

原型和原型继承不是特定于JavaScript的。 它们是JavaScript内部使用的结构,允许我们在自己的程序中使用它。 在研究如何精确地做到这一点之前,我们需要了解什么是原型链。

原型链 (Prototypal Chaining)

We’ll need to get back to the buttons analogy for once. Let’s say I want to create a large solid button, .btn-solid-lg:

我们需要一次回到类比按钮。 假设我要创建一个大的实心按钮.btn-solid-lg

The base styles to .btn-solid-lg are supplied by .btn-solid, and .btn-solid-lg overwrites the font-size property to create itself.

.btn-solid-lg的基本样式由.btn-solid.btn-solid-lg覆盖font-size属性以创建其自身。

Take a closer look though. .btn-solid has just two styles background-color and color (font) defined on it. This means .btn-solid-lg has just 3 styles for itself: background-color, color, and font-size. Where are width, height, border-radius coming from?

仔细看看。 .btn-solid仅有两种样式,背景颜色和定义的颜色(字体)。 这意味着.btn-solid-lg本身只有3种样式:background-color,color和font-size。 widthheightborder-radius从何而来?

Ok, here’s a hint:

好的,这里有个提示:

If you wanted to create an extra large button .btn-solid-xlg you could do so with .btn-solid-lg as prototype. But how does all of this map to JavaScript?

如果您想创建一个超大按钮.btn-solid-xlg ,可以使用.btn-solid-lg作为原型。 但是所有这些如何映射到JavaScript?

In JavaScript, you’re allowed to create prototype chains too. Once you understand this, you unlock a whole set of tools to write amazingly powerful code. Yes, amazingly powerful.

在JavaScript中,您也可以创建原型链。 一旦了解了这一点,便可以解锁整套工具来编写功能强大的代码。 是的, 功能强大

Let’s see how prototype chains in JavaScript work.

让我们看看JavaScript中的原型链如何工作。

Remember the object we created in the previous section? The one we carefully named obj? Did you know that you can create as many objects as you want with obj as a prototype?

还记得我们在上一节中创建的对象吗? 我们仔细命名为obj那个? 您是否知道可以使用obj作为原型创建尽可能多的对象?

Object.create lets you create a new object from a specified prototype object. This means that you can create another object, obj2, which has obj as its first prototype:

Object.create允许您从指定的原型对象创建新对象。 这意味着您可以创建另一个对象obj2 ,该obj的第一个原型为obj

let obj2 = Object.create(obj);
// Add a property 'b' to obj2obj2.b = 2;

If you have been following so far, you should realize that even though obj2 doesn’t have a property a defined on it, doing console.log(obj2.a) won’t result in an error, but instead 1 getting logged to the console. Kind of like this:

如果你一直到目前为止之后,你应该明白,即使obj2没有一个属性a定义就可以了,这样做console.log(obj2.a)不会导致错误,而是1得到记录到安慰。 有点像这样:

When obj2 looks for a, it first searches its own properties. If it can’t find the corresponding property, it asks its prototype (obj), where it finally finds a. If such was the case that it still couldn’t find a, the search would continue up the prototype chain until it reaches the last link, Object.prototype.

obj2查找a ,它首先搜索其自己的属性。 如果无法找到相应的属性,它要求其原型(OBJ),在那里它终于找到a 。 如果仍然无法找到a ,则搜索将继续在原型链上进行,直到到达最后一个链接Object.prototype

On the other hand, if a was defined on obj2, it would override all other as if defined on any of its prototypes. Similar to how .btn-solid overrode .btn's color and background-color properties. This is called property overshadowing.

在另一方面,如果a被定义obj2 ,它会覆盖所有其他a ,如果在任何原型定义秒。 类似于.btn-solid如何覆盖.btncolorbackground-color属性。 这称为财产遮盖

But what about the length of prototype chain? Is there a limit?

但是原型链的长度呢? 有限制吗?

There’s no limit to the length of prototype chain. There also aren’t any limits on branching. This means you can create multiple instances with Object.prototype, obj, or obj2 as prototype.

原型链的长度没有限制。 分支也没有任何限制。 这意味着您可以使用Object.prototypeobjobj2作为原型创建多个实例。

So how will this new knowledge of prototypes and prototypal chaining help you write better code?

那么,有关原型和原型链的新知识将如何帮助您编写更好的代码?

用原型编写更好的代码 (Writing better code with Prototypes)

The goal of this article was to explain to you what prototypes are, and how prototypal inheritance works. I hope I’ve succeeded in this.

本文的目的是向您解释什么是原型,以及原型继承如何工作。 我希望我已经成功了。

For this last section, I’ll allow myself to go on a little rant. I hope you don’t mind.

在最后一部分中,我将允许自己继续讲一点。 我希望你不要介意。

If you look at the JavaScript code available online — whether in open source projects on Github or in pens on Codepen — you’ll find that a majority of them use the constructor pattern for creating objects.

如果您查看在线上可用JavaScript代码(无论是在Github上的开源项目中还是在Codepen上的钢笔中),您会发现其中大多数使用构造函数模式来创建对象。

function Circle(radius) {  this.radius = radius;}
Circle.prototype.area = function() {  return Math.PI * this.radius * this.radius;}
// Constructor pattern for creating new objectslet circ = new Circle(5);

The constructor pattern looks like classes. In the early days, when JavaScript was far less popular than what it is today, the new keyword was added as a marketing strategy.

构造函数模式看起来像类。 在早期,JavaScript远不如今天流行, new关键字被添加为一种营销策略。

This indirection was intended to make JavaScript seem more familiar to classically trained programmers. Though it’s debatable how successful it was in doing so, it unintentionally also obscured the true prototypal nature of the language.

这种间接作用旨在使受过经典训练的程序员对JavaScript更加熟悉。 尽管这样做的成功程度值得商bat,但它无意间也掩盖了语言的真正原型性质。

The reality is that although constructors look like classes, they don’t behave like classes at all. In JavaScript, there are objects, and objects extending from other objects. Constructors and classes never come into picture. The constructor pattern unnecessarily complicates things, there’s a lot that happens behind the scenes.

现实情况是,尽管构造函数看起来像类,但它们的行为完全不像类。 在JavaScript中,存在对象,以及从其他对象扩展的对象。 构造函数和类永远不会出现。 构造函数模式不必要地使事情复杂化, 幕后发生了很多事情。

I implore you — now that you have a solid understanding of prototypes — to stop using the constructor pattern.

我恳请您-现在您已经对原型有了深刻的了解-停止使用构造函数模式。

Why not do this instead?

为什么不这样做呢?

let Circle = {  create(radius) {    // Creating prototypal linkage using Object.create    let obj = Object.create(this);    obj.radius = radius;    return obj;  },  area() {    return Math.PI * this.radius * this.radius;  }};
let circ = Circle.create(5);

I hope this analogy has helped you better understand prototypes, prototypal chaining and prototypal inheritance with Object.create. Now you can write better code, and stop using pretentious classes.

我希望这种类比可以帮助您更好地理解Object.create原型,原型链和原型继承。 现在您可以编写更好的代码,并停止使用自命不凡的类。

Thanks for reading! If my article was helpful, click the little green heart below to recommend it, and please share this with your fellow devs.

谢谢阅读! 如果我的文章有帮助,请单击下面的绿色小心脏以推荐它,并与其他开发人员分享。

And for further reading, check out Aadit Shah’s Why Prototypal Inheritance Matters.

要进一步阅读,请查看Aadit Shah的“ 为什么原型继承很重要”

寻找更多? 我定期在我的博客nashvail.me上发布 到那里见,祝你好运! (Looking for more? I publish regularly on my blog at nashvail.me. See you there, have a good one!)

翻译自: https://www.freecodecamp.org/news/understanding-prototypal-inheritance-in-javascript-with-css-93b2fcda75e4/

css 原型图片

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值