How does prototypal inheritance work in JavaScript?

I'm still not fully understanding the inheritance dichotomy (prototypal and classical) in JavaScript.

If class

it's just syntactic sugar over prototypes, how am I supposed to skim it?

Can you show me different approaches to creating React elements with classes and prototypes (i.e. without class

and React.createClass

)?

So, is there a way to get a stateful component using native Object.create

?

Like this:

const Hello = Object.create(React.Component.prototype, {
  componentDidMount: {
    value: function() {
      alert('Mounted');
    }
  },
  render: {
    value: function() {
      return <div>I love StackOverflow community! It is so helpful and friendly</div>;
    }
  }
});

ReactDOM.render(<Hello />, document.getElementById('root'));

      

Something like this doesn't seem to work due to the limitations of the internal libs. But why can't we use it in a more natural way for JavaScript prototyping?

This is a note from the official docs: https://facebook.github.io/react/docs/composition-vs-inheritance.html#so-what-about-inheritance

[...] we did not find any use cases where we recommend creating component inheritance hierarchies

But not class

mainly about inheritance?

I am very confused and would like to hear your opinion on what I am doing and think wrong?

Ive asked that question in Reactiflux and Brendan Hurley suggested the following: https://codepen.io/niechea/pen/xdVEvv?editors=0010

function MyComponent(props) {
  this.props = props;
  this.state = {
    clickCount: 0,
  };
}

MyComponent.prototype = Object.create(React.Component.prototype);

MyComponent.prototype.clickHandler = function() {
  this.setState({
    clickCount: this.state.clickCount + 1,
  });
}

MyComponent.prototype.render = function() {
  return (
    <div>
      <p>Hello, {this.props.name}.</p>
      <p>You have clicked {this.state.clickCount} time(s)!</p>
      <button onClick={this.clickHandler.bind(this)}>Click me</button>
    </div>
  );
}

ReactDOM.render(<MyComponent name="Bogdan" />, document.getElementById('app'));

      

Is his solution really a prototype?


Here are some links:


* The question is mostly about inheritance, not reagent. React here is just a link.

+4


source to share


6 answers


If a class is just syntactic sugar over prototypes, how am I supposed to skim it?

For example, this is a good article on the subject. Therefore, if you created an object Animal

with class

:

class AnimalES6 {
    constructor(name) {
        this.name = name;
    }

    doSomething() {
        console.log("I'm a " + this.name);
    }
}

var lionES6 = new AnimalES6("Lion");
lionES6.doSomething();

      

The prototype version will look something like this:

var Animal = (function () {
    function Animal(name) {
        this.name = name;
    }
    // Methods
    Animal.prototype.doSomething = function () {
        console.log("I'm a " + this.name);
    };
    return Animal;
})();

var lion = new Animal("Lion");
lion.doSomething();

      

This is further complicated with a function extend

(like TypeScript inheritance modeling):

var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};

      

Can you show me different approaches for creating React elements with classes and prototypes (i.e. no class and React.createClass)?



This question has already been asked SO questions, for example. this one .

But still, in my opinion, the real question is: do you want?

Since you linked Eric Elliot's article, you probably noticed that there is some sort of controversy in the javascript world around EC6 class

es. Apart from the examples you gave, there are several generalizations of opinions from more developers, for example. this is the github repo , here and more. There are also articles defending the purpose class

...

Anyway, the makers of React seem to have embraced class

es's "anger" , and as you pointed out, you will run into problems when trying to use the prototypical approach with React. So, in my opinion: why fight it? I also like the prototypal nature of JavaScript and I also like the ReactJS framework, but in my opinion it would be better to come up with some new framework that combines the best of both, something like "Protypal React" rather than trying provide prototyping for React, if it is not intended for such use.

But isn't a class mostly about inheritance?

This was probably answered in the comments, but no. Classes have their advantages as they have a design concept Composition

over inheritance. It depends on the needs , but many frameworks / libraries are built in object oriented languages ​​that use a class that covers composition over inheritance, for example. Unity.

Really good question anyway, and I wanted to share my thoughts on the matter. Hope this helps you form an opinion.

+1


source


So, as others have said, the best way to think about classes in Javascript is with syntactic sugar over prototypal inheritance. It is best to avoid association of classical inheritance with classes in other languages, especially if you were taught this at university / school.

Prototypal inheritance can be considered more expressive than classical inheritance.

Using the 'class' keyword in JS is syntactically closer to classical inheritance.

For example, you have these components in your user interface: Link, MediaLink, ImageLink, and VideoLink. In classic inheritance, it might be tempting to have a Link class, a MediaLink class that extends links, and VideoLink and ImageLink classes that extend the MediaLink class, where MediaLink is an abstract class (not instantiated). If you were to implement this hierarchy with Realact React components using prototypal inheritance, then in theory it would be easy to manipulate states by calling super (or calling React.Component.apply(this, props);

as in the answer above), however, the core of React, that is, "render", would be a little abstract and difficult to pass. Link may return<a ...>link</a>

what would MediaLink return? How would VideoLink handle its parent's return? Or are you starting to deny the parent render functions and replace them entirely? At this point, it gets uncomfortable and it starts to look a bit like spaghetti.



Instead, you can compose components. In classic inheritance, you can represent your Component class as a final class inherited from the abstract class , React.Component. To accomplish the above, you add behavior to your class, which can be common to many classes. For example, the TextLink, VideoLink, and ImageLink components have the "clicked" boolean state. I think this article describes these ideas very well.

Another way to lay out components is to wrap the components in other components and pass state through props to their children. A very crude example would be: Link, SwitchedLink. The Link class has an 'active' option that determines whether it is active or not. Dial-up connection will display either <Link />

or <Link active />

both a single child element, depending on its own status. Stateless child. The parent has a fortune. These are common patterns with React and hence why there is no need for the classic multi-level inheritance structure.

Hope you can answer your question.

+1


source


There are two types of component in React; functional component and class-based component. Below is a link to online docs explaining the difference.

It's interesting to note that a component in a reagent is essentially a function that returns some amount of JSX. This way, you can write a function and return JSX, and it will be a component, but without the internal details lifecycle methods

such as componentWillMount

, this.props

and this.state

, which Class Component

windows will give you.

So, you can create a functional component (like a function that returns JSX) and prototype it like this

const Card = (props) => {
this.sayHello = function () {
  console.log('hello hello hello');
};

return (  
  <View style={styles.containerStyle}>
    {props.children}
    { this.sayHello() }
  </View>
 );
};

      

and that will be passed for a Component built in Reactit without the usual terminology you are used to.

Hope this is helpful

0


source


I think it is important to break things down easily to understand. You are asking about prototypal inheritance in JavaScript, and then how this relates to React. First of all, I must say that the prototype is not easy to explain and is not documented, but it allows you to focus on one thing at a time. So yes, JavaScript has no concept of object inheritance, but prototypal inheritance instead. Lets you create a function on cars:

function Car() {

}

      

Then we can make Toyota inherit Car

. So let's see what a constructor function looks like when using classes.

function Car(options) {
  this.title = options.title;
}

      

Therefore, everyone Car

should have options

transmitted to him, and it options

has title

.

Now we can create a new car and pass an options

object to it title

like this:

const car = new Car({ title: 'Focus' });
car;

      

Now let's add a method to this class Car

, so we add this method to the constructor prototype object like this:

Car.prototype.drive = function() {
  return 'vroom!';
}

      

Now when we call car.drive();

we get the result vroom!

,

So this is basic object creation with JavaScript. We create a constructor object, then use a new

keyword on it, and then we can add methods to the object, but add it to the prototype property of the constructor:

constructorFunction.prototype.methodWeAdd = function() {
  return something;
};

      

Now I will add an object that inherits from Car

to set the prototype link.

So I will make Toyota and I want it to inherit this object Car

like so:

function Toyota(options) {

}

      

So I passed an object options

as an argument that contains the color

car.

function Toyota(options) {
  this.color = options.color;
}

const toyota = new Toyota({ color: 'grey', title: 'Prius' });
console.log(toyota);

      

So I want Toyota to inherit all properties and methods Car

because toyota

- this Car

. So how do I create a link between the two? How can I delegate toyota

to be able to call all the methods it has Car

?

So whenever I call a Toyota

constructor, I want me to trigger any initialization that happens in Car

and also like this:

function Toyota(options) {
  Car.call(this.options);
  this.color = options.color;
}

      

I also want to make sure I can name the drive method Car

on the object Toyota

like this:

Toyota.prototype = Object.create(Car.prototype);
Toyota.prototype.constructor = Toyota;

      

Now I should be able to add a method to the prototype Toyota

like:

Toyota.prototype.honk = function() {
  return 'beep beep!';
};

      

Now I can call the following:

const toyota = new Toyota({ color: 'grey', title: 'Prius' });
console.log(toyota);
console.log(toyota.drive());
console.log(toyota.honk());

      

Therefore, it toyota

must inherit some level of customization that comes from Car

. So the aforementioned painful process that I just tried is to tell you, this is how you disabilize it in plain vanilla JavaScript. Not sure why you would like to, but here it is.

So the above is about how prototypal inheritance is done in JavaScript.

The idea behind classes is not only syntactic sugar, but also to remove such a painstaking process from our workload so that we can focus on other application development issues.

When you look at new developments like ES6, yes, some of them fall under syntactic sugar, but the idea is to remove or allow a painstaking process from a day to day task like creating classes or accessing properties / methods from an object. such as destruction.

In practice, the JavaScript community has included the use of classes, you will see a ton of libraries using classes, whereas template strings and destructuring were nice additions, classes have dramatically changed the way JavaScript is written.

Much because of how it was difficult to write a prototype-based inheritance, while his classes much easier to use class

and extend

keywords.

When React first came out, the idea of ​​using prototypal inheritance all over the place to create a component was considered ridiculous just because you have to make so many customizations (as you saw above) whenever you create a subclass that inherits from another object. Instead, we'll use a helper to create the component createClass

. This is part of React, but I want to show you an example of where some existing library has been ported to classes.

So it was that with React we had this helper called createClass:

React.createClass({

});

      

And you will pass in an object, and it might have a method like this:

React.createClass({
   doSomething() {

   },

   doSomethingElse() {

    }
});

      

It wasn't the worst in the world, but it definitely made it really hard when you wanted to subclass a component or create a component with some behaviors and reuse it somewhere else. These days React has moved to using class syntax like:

class MyComponent extends Component {
    doSomething() {

    }

    doSomethingElse() {

    }
}

      

The advantage of this approach is that if I want to make some kind of generic, very reusable component to be used somewhere else in my codebase, I can make it much easier with a class based approach instead of using syntax createClass()

and is certainly much simpler than the prototype inheritance syntax method.

You will also notice that the inheritance chain is much more obvious. Thus, this Component keyword is a generic component provided by the React library.

Anyone who looks into this class can see that it is creating a component and borrowing functionality from Component

.

The advantage of this is that if you are a fan of object oriented programming and are working with React, the class syntax is generally easier to work with than the old syntax createClass()

.

0


source


Prototype inheritance is when you put a method in the original constructor

function Cat(name,breed){
   this.name = name;
   this.breed = breed;
}

      

This will be inherited from the rest

const susie = new Cat('Susie', 'Persian');

      

If I create a new array, const names = ['Gilbert','Mia']

I just created a new array, but now names.join()

is a method names.pop)()

is a method.

enter image description here

We have all of these methods on top of the names. Where did they come from? Well we have the mother of Array

capital A

If you look inside it, you will find out that Array

there are many prototype methods,

enter image description here

which means that when you create Cat

const susie = new Cat('Susie', 'Persian');

      

from solid mother or from Cat

mother

function Cat(name,breed){
   this.name = name;
   this.breed = breed;
}

      

every instance of this inherits these methods.

function Cat(name,breed){
   this.name = name;
   this.breed = breed;
}
Cat.prototype.meow = function() {
   Console.log('Meow meow! My name is ${this.name}');
}

const susie = new Cat('Susie', 'Persian');
const mimi = new Cat('Mimi', 'Persian');
      

Run codeHide result


Now you can see that the prototype is Cat.prototype.meow

now inherited by every cat instance.

const susie = new Cat('Susie', 'Persian');
const mimi = new Cat('Mimi', 'Persian');

      

susie.meow();

→ Meow meow! My name is Susie mimi.meow();

→ Meow meow! My name is mimi

0


source


Sorry, I cannot write a comment. I think you should initialize the superclass constructor below.

function MyComponent(props) {
  React.Component.prototype.apply(this, props);
  this.props = props;
  this.state = {
    clickCount: 0,
  };
}

      

-1


source







All Articles