Prototypal Inheritance: Subclasses

Subclasses

One of the benefits of implementing inheritance is that it allows you toreuse existing code. By establishing inheritance, we cansubclass, that is, have a "child" object take on most or all of a "parent" object's properties while retaining unique properties of its own.

Let's say we have a parentAnimalobject, which contains properties likeageandweight. That sameAnimalobject can also access methods likeeatandsleep.

Now, let's also say that we want to create aCatchild object. Just like you can with other animals, you can also describe a cat by itsage_or_weight, and you can also be certain that the cat_eats_and_sleeps_as well. When creating thatCatobject, then, we can simply re-write and re-implement all those methods and properties fromAnimal-- or, we can save some time and prevent repeated code by havingCat_inherit_those existing properties and methods fromAnimal!

Not only canCattake on properties and methods ofAnimal, we can also giveCatits own unique properties and methods as well! Perhaps aCathas a uniquelivesproperty of9, or it has a specializedmeow()method that noAnimalhas.

By using prototypal inheritance,Catonly needs to implementCat-specific functionality, and just reuseAnimal's existing functionality.

implementing inheritance(상속 구현)의 이점 중 하나는 기존 코드를 재사용할 수 있다는 것입니다. 상속을 설정함으로써 subclass를 만들 수 있습니다. 즉, "자식"object가 고유한 속성을 유지하면서 "부모"object의 속성 대부분 또는 전부를 가져갈 수 있습니다.

age과 weight과 같은 속성을 포함하는 상위 Animal object가 있다고 가정해 보겠습니다. 동일한 Animal object는 eat 및 sleep과 같은 method에 액세스할 수 있습니다.

자, Cat이라는 자식object를 만든다면, 다른 동물과 마찬가지로 cat의 age이나 weight을 설명할 수 있으며, cat이 eat 및 sleep도 확신 할 수 있습니다. 그런 다음 Cat object를 만들면 Animal에서 모든 method와 속성을 다시 작성하고 다시 구현할 수 있습니다. 또는 Cat이 Animal에서 기존 속성과 method를 상속받도록하여 반복 코드를 방지할 수 있습니다.

Cat은 Animal의 속성 및 method를 사용할 수 있을뿐만 아니라 Cat에 고유한 속성 및 method도 제공 할 수 있습니다. 아마도 cat는 독특한 lives 속성이 9이거나, animal에 없는 특수화된 meow() method가 있습니다.

Prototype inheritance를 사용함으로써 Cat은 Cat 고유의 기능을 구현하고 Animal의 기존 기능을 재사용하면 됩니다.

Inheritance Via Prototypes

Recall the prototype chain from the previous section:

TheCat()constructor function is invoked using thenewoperator, which creates thebaileyinstance (object). Note that themeow()method is defined in the prototype of thebaileyobject's constructor function. The prototype is just an object, and all objects created by that constructor are secretly linked to the prototype. As such, we can executebailey.meow()as if it werebailey's own method!

Cat() constructor 함수는 "new"operator를 사용하여 호출됩니다.이 operator는 bailey instance (object)를 만듭니다. meow() method는 bailey object의 constructor 함수의 prototype에 정의되어 있습니다. prototype은 단지 하나의 object이며, 그 constructor에 의해 생성된 모든 object는 prototype에 비밀리에 연결됩니다. 따라서 bailey.meow()를 bailey 자신의 method처럼 실행할 수 있습니다!

When calling any property on any object, the JavaScript engine will first look for the property in the object itself (i.e., the object'sown, non-inherited properties). If the property is not found, JavaScript will then look at the object's prototype. If the property_still_isn't found in the object's prototype, JavaScript will continue the search up theprototype chain.

Again, inheritance in JavaScript is all about setting up this chain!

As you know, an object's constructor function's prototype is first place searched when the JavaScript engine tries to access a property that doesn't exist in the object itself. Consider the followingbearobject with two properties,clawsanddiet:

const bear = {
  claws: true,
  diet: 'carnivore'
};

We'll assign the followingPolarBear()constructor function'sprototypeproperty tobear:

function PolarBear() { 
  // ...
}

PolarBear.prototype = bear;

Let's now call thePolarBear()constructor to create a new object, then give it two properties:

const snowball = new PolarBear();

snowball.color = 'white';
snowball.favoriteDrink = 'cola';

This is how thesnowballobject looks at this point:

{
  color: 'white',
  favoriteDrink: 'cola'
}

Note thatsnowballhas just two properties of its own:colorandfavoriteDrink. However,snowball_also _has access to properties that _don't _exist inside it:clawsanddiet:

console.log(snowball.claws);
// true

console.log(snowball.diet);
// 'carnivore'

Sinceclawsanddietboth exist as properties in theprototypeobject, they are looked up because objects are _secretly linked _to their constructor'sprototypeproperty.

Great! But you may be wondering: just _what _is this secret link that leads to theprototypeobject? Right after objects are made from thePolarBear()constructor (such assnowball), they have immediate access to properties inPolarBear()'s prototype. How exactly is this possible?

As it turns out, the secret link issnowball's__proto__property (note the two underscores on each end).__proto__is a property of all objects (i.e., instances) made by a constructor function, and points directly to that constructor'sprototypeobject. Let's check out what it looks like!

console.log(snowball.__proto__);

// { claws: true, diet: 'carnivore' }

Since the__proto__property refers to the same object asPolarBear's prototype,bear, comparing them returnstrue:

console.log(snowball.__proto__ === bear);

// true

It is highly discouraged to reassign the__proto__property, or even use it in any code you write. First, there compatibility issues across browsers. What's more: since the JavaScript engine searches and accesses properties along the prototype chain, mutating an object's prototype can lead to performance issues. The MDN article forprotoeven warns against using this property in red text at the very top of the page!

It's great toknowthe secret link for learning how functions and objects are interconnected, but you**should not use`\_proto_to manage inheritance**. If you ever just need to review an object's prototype, you can still useObject.getPrototypeOf()`.

💡 What About Just Inheriting the Prototype? 💡

Let's say we want aChildobject to inherit from aParentobject. Why shouldn't we just setChild.prototype = Parent.prototype?

First, recall that objects are passed byreference. This means that since theChild.prototypeobject and theParent.prototypeobject refer to thesame object-- any changes you make toChild's prototype will_also_be made toParent's prototype! We don't want children being able to modify properties of their parents!

On top of all this, no prototype chain will be set up. What if we want an object to inherit from any object we want, not just its prototype?

We still need a way to efficiently manage inheritance without mutating the prototype at all.

QUESTION 1 OF 4

Consider the following:

function GuineaPig (name) {
  this.name = name;
  this.isCute = true;
}

const waffle = new GuineaPig('Waffle');

What doeswaffle.__proto__refer to?

  • GuineaPig.__proto__

  • GuineaPig.proto

  • GuineaPig.prototype

  • guineapig.proto

  • GuineaPig

SUBMIT: When the new instance of GuineaPig is created, the special property waffle.__proto__ is set to GuineaPig.prototype . This secret link allows instances of the GuineaPig constructor to access properties of GuineaPig.prototype . Keep in mind that you should never use the __proto__ in any code you write.

QUESTION 2 OF 4

Consider the following:

function Car (color, year) {
  this.color = color;
  this.year = year;
}

Car.prototype.drive = function () {
  console.log('Vroom vroom!');
};

const car = new Car('silver', 1988);

What happens whencar.drive();is executed? List the following events in the order that they occur:

BecauseCar.prototype.drive_is_a defined property, it is returned.

The JavaScript engine then accesses thecar.__proto__property.

The JavaScript engine does not finddrivewithin thecarobject.

First, the JavaScript engine searches inside thecarobject for a property nameddrive.

Since thecar.__proto__property points toCar.prototype, the JavaScript engine searches fordrivein the prototype.

Finally, sincedriveis invoked as a method oncar, the value ofthisis set tocar.

ORDER

EVENT

1st: First, the JavaScript engine searches inside thecarobject for a property nameddrive.

2nd: The JavaScript engine does not finddrivewithin thecarobject.

3rd: The JavaScript engine then accesses thecar.__proto__property.

4th: Since thecar.__proto__property points toCar.prototype, the JavaScript engine searches fordrivein the prototype.

5th: BecauseCar.prototype.drive_is_a defined property, it is returned.

6th: Finally, sincedriveis invoked as a method oncar, the value ofthisis set tocar.

SUBMIT: This is the prototype chain in action! As always: keep in mind that while the secret link is the __proto__ property, it should never be used (written) directly.

Object.create()

At this point, we've reached a few roadblocks when it comes to inheritance. First, even though__proto__can access the prototype of the object it is called on, using it in any code you write is not good practice.

What's more: we also shouldn't inherit _only _the prototype; this doesn't set up the prototype chain, and any changes that we made to a child object will also be reflected in a parent object.

So how should we move forward?

There's actually a way for us to set up the prototype of an object ourselves: usingObject.create(). And best of all, this approach lets us manage inheritance without altering the prototype!

Object.create()takes in a single object as an argument, and returns a new object with its__proto__property set to what argument is passed into it. From that point, you simply set the returned object to be the prototype of the child object's constructor function. Let's check out an example!

우리는 prototype만 상속받아서는 안됩니다. 이것은 prototype chain을 설정하지 않으며 우리가 자식 object에 변경한 사항은 부모 object에도 반영됩니다.

그렇다면 앞으로 어떻게 나아가야합니까?

Object.create()를 사용하여 object의 prototype을 직접 설정할 수있는 방법이 있습니다. 그리고 무엇보다도이 접근법은 prototype을 변경하지 않고 상속을 관리할 수 있게 해줍니다!

Object.create()는 단일 object를 argument로 사용하고 __proto__ 속성이 전달된 argument로 설정된 새 object를 반환합니다. 그 시점에서 반환된 object를 자식 object의 생성자 함수의 prototype으로 설정하기만하면 됩니다. 예를 들어 봅시다!

First, let's say we have amammalobject with two properties:vertebrateandearBones:

const mammal = {
  vertebrate: true,
  earBones: 3
};

Recall thatObject.create()takes in a single object as an argument, and returns a new object. That new object's`\_proto_property is set to whatever was originally passed into Object.create(). Let's save that returned value to a variable,rabbit`:

const rabbit = Object.create(mammal);

We expect the newrabbitobject to be blank, with no properties of its own:

console.log(rabbit);

// {}

However,rabbitshould now be secretly linked tomammal. That is, its__proto__property should point tomammal:

console.log(rabbit.__proto__ === mammal);

// true

Great! This means that now,rabbitextendsmammal(i.e.,rabbitinherits frommammal). As a result,rabbitcan accessmammal's properties as if it were its own!

console.log(rabbit.vertebrate);
// true

console.log(rabbit.earBones);
// 3

Object.create()gives us a clean method of establishing prototypal inheritance in JavaScript. We can easily extend the prototype chain this way, and we can have objects inherit from just about any object we want!

Object.create()는 JavaScript에서 prototype 상속을 설정하는 깔끔한 method를 제공합니다. 우리는 이 방법으로 prototype chain을 쉽게 확장할 수 있으며, 우리가 원하는 모든 object로부터 object를 상속받을 수 있습니다!

Let's check out a more involved example below:

VIDEO

Here's the code from the preceding video.

QUESTION 3 OF 4

Consider the following:

function Parent() {
  // ...
}

function Child() {
  // ...
}

Child.prototype = Object.create(Parent.prototype);

const child = new Child();

The following is then executed:

child instanceof Parent;

What is printed to the console?

  • Child

  • undefined

  • false

  • true

  • The console will throw an error.

SUBMIT: Object.create() takes in a single object as an argument, and returns a new object. That new object's `__protoproperty is set to whatever was originally passed intoObject.create()`.

In this quiz,Parent.prototype was the argument passed into Object.create(). The return value of the expression Object.create(Parent.prototype); was then set to the value of the Child constructor's prototype property. After that, we instantiate a new object:child`.

The expressionchild instanceof Parent;returns a boolean indicating whether the Parentconstructor exists in thechildobject's prototype chain. Since we know this is true after executing the first expression (i.e.,Child.prototype = Object.create(Parent.prototype);), the console outputs true.

QUESTION 4 OF 4

What is true aboutObject.create()? Select all that apply:

  • It returns a new object whose__proto__property is set to the object passed intoObject.create()

  • UsingObject.create(), we can have objects inherit from just about any object we want (i.e., not only theprototype)

  • Object.create()allows us to implement prototypal inheritance without mutating the prototype

  • The method is invoked directly_on_a single object

SUBMIT: Object.create() is a practical approach to establish prototypal inheritance in JavaScript.

Summary

Inheritance in JavaScript is all about setting up the prototype chain. This allows us to subclass, that is, create a "child" object that inherits most or all of a "parent" object's properties and methods. We can then implement any of the child object's unique properties and methods separately, while still retaining data and functionality from its parent.

An object (instance) is secretly linked to its constructor function's prototype object through that instance's __proto__property. You should never use the__proto__in any code you write. Using __proto__in any code, or even inheriting just the prototype directly, leads to some unwanted side effects.

To efficiently manage inheritance in JavaScript, an effective approach is to avoid mutating the prototype completely. Object.create()allows us to do just that, taking in a parent object and returning a new object with its `\_proto_` property set to that parent object.

JavaScript의 상속은 모두 prototype 체인을 설정하는 것입니다. 이것은 하위 클래스로 만들 수 있습니다. 즉, "부모"object의 속성 및 method 대부분 또는 모두를 상속하는 "자식"object를 만듭니다. 그런 다음 부모로부터 데이터와 기능을 유지하면서 자식 object의 고유 한 속성과 method를 개별적으로 구현할 수 있습니다.

object (인스턴스)는 해당 인스턴스의 __proto__ 속성을 통해 생성자 함수의 prototype object에 몰래 연결됩니다. 당신이 쓰는 모든 코드에서 __proto__를 사용해서는 안됩니다. 임의의 코드에서 __proto__를 사용하거나 직접 prototype을 상속하는 경우에도 원치 않는 부작용이 발생합니다.

JavaScript에서 상속을 효율적으로 관리하려면 효과적인 prototype 변형을 피하는 것이 좋습니다. Object.create()는 부모 object를 가져 와서 `\ _proto_` 속성을 부모 object로 설정하여 새로운 object를 반환하는 것을 허용합니다.

Further Research

results matching ""

    No results matching ""