preface

Traditional OOP languages, such as Java, use abstract design of classes to implement the three characteristics of object orientation: encapsulation, inheritance, and polymorphism. With the popularity of such languages, this has become a very classical programming paradigm. But there are no real classes in JS, or to put it more accurately, classes in JS are very different from classes in Java.

Many come to it from other language programmer puzzled, so they think the js is not a true object-oriented language, because they can’t understand there is new in js, object, but there is no class, if the function analogy for Java classes, it even before the es6 out even the most basic grammar have no inheritance. They even invented a new term to describe object systems in JS, such as “object based” rather than object oriented, in order to explain this phenomenon specifically.

However, the author thinks that, thinking should not be rigid, at least not completely copy hard set of previous experience to learn a new language, whether true object-oriented and whether to implement with class, cannot draw the equal sign, in other words, the class is just a way of implementation of object-oriented, obviously, js designers chose another: based on the prototype.

The body of the

Simulate the implementation of a class in JS

Subclass inherits a parent class in Java, is the need to open up a new space, from the parent class method attributes to copy a subclass, that is to say, these properties and inheritable method in a subclass to create success, has nothing to do, then a method of the parent class change, also won’t affect the subclass, instance is even more so, You can simply think of it as a one-off physical copy. But in JS, you don’t copy, you share.

Implementation of Java class inheritance in JS:

Function Parent(name){this.name = name} // Add the sayName method on the Parent class to parent.prototype.sayName = Function (){console.log(this.name)} function Child(age,... p){ Parent.call(this,... P) // This is similar to super in Java, which is a pointer to the superclass. Prototype = object.create (parent.prototype) // Add a sayAge method on the prototype to the subclass Child.prototype.sayAge = function(){ console.log(this.age) } const obj = new Child(18,'lili') console.log(obj) // Obj.sayname () obj.sayage () obj.sayage ()Copy the code

Next, what happens when you try to change a “parent” method.

. Parent.prototype.sayName = null obj.sayname () // TypeError obj.sayname is not a functionCopy the code

The sayName method overridden on the parent class will affect the performance of the method call on the parent instance in real time. Therefore, the relationship between the “class” method and the instance method is not simply copy and copy, but share the same method reference. As you can see, the above code is complex and long, the performance of the simulation is also very far-fetched, so it is not easy to simulate the implementation of other language classes in JS.

The new classes in ES6 are exactly the same as those in Java.

class Parent{
    constructor(name){
      this.name = name
    }
    sayName(){
      console.log(this.name)
    }
  }
class Child extends Parent{
    constructor(age,name){
      super(name)
      this.age = age;
    }
    sayAge(){
      console.log(this.age)
    }
}
const obj = new Child(18,'lili');
obj.sayName() // 'lili'
Parent.prototype.sayName = null 
obj.sayName() // TypeError obj.sayName is not a function
Copy the code

So classes in ES6 are just syntactic sugar inherited from ES5 archetypes, and the nature of sharing hasn’t changed at all.

A prototype-based delegation pattern

You probably don’t need classes

Back to js application scenarios, in most cases, the front end does not need to carry too much business logic, so the abstract use of the class is not very big, we might as well recall, you think in THE JS code to write a very beautiful class, are really new how many times? Take a frequently used framework like Vue for example. Most applications will only find new vue (…) in index.js. It is also possible to use an object called a VUE directly once, and the slightly persuasive advantage is that the constructor form of a VUE allows the code to be organized more aggregated and with fewer global variables than the direct object form.

Class Vue{constuctor(){$set(..); {... }... Function createVue(..) { return { $set(..) {... }} function initHandlers(vue){} function initHandlers(vue){ )Copy the code

Nature of object

Object is not that mysterious per se, it is just a packet containing attribute data. Also, using the new keyword is not mandatory when creating objects in JS.

const obj = {
  age:1,
  name:'lili'
}
Copy the code

So how do you reuse property methods

const obj = {
  sayName(){
    console.log(this.name)
  }
}

const obj1 = Object.create(obj)
obj1.name = 'lili';
obj1.sayName() // 'lili'
Copy the code

It’s a little bit more intuitive down here

const obj = { sayName(){ console.log(this.name) } } const obj1 = { name:'lili' } Object.setPrototypeOf(obj1,obj); Obj1.__proto__ = obj; obj1.sayName() // 'lili'Copy the code

The es5 Object. Create or es6 Object. SetPrototypeOf functions are the same. They are used to establish associations between two objects, facilitating the sharing of properties and methods.

The meaning of the constructor

As you know, most of the capabilities in JS, if not provided by the global method on the window, are most likely provided by various built-in objects. The creation of built-in objects depends on one built-in constructor after another, such as Array ‘ ‘Date’ ‘RegExp, etc. So constructors themselves are a form of THE API that JS provides in the first place. Use constructors to establish associations between two objects

function Contructor(name){
    this.name = name;
}
Contructor.prototype.sayName = function(){
    console.log(this.name)
}
const instance = new Contructor('lili');
instance.sayName() // lili
Copy the code

Contructor is just a normal function. When you create this function, JS automatically creates a Contructor. Prototype object. You can add properties and methods to this object directly, so this can be the NTH way to create objects in JS. And when you call Contructor with the new keyword, it acts as a constructor. It can pass parameters to customize the object content, and it can automatically “return” the new object for you, so it is much more convenient than the pure manual creation of the prototype below.

Const prototype = {sayName(){console.log(this.name)}} function createObj(name){return {name Const instance = createInstance('lili') instance.__proto__ = prototype; SetPrototypeOf (instance,prototype) instance.sayname ()Copy the code

The meaning of class syntax

Summarize the above requirements:

  • Create objects by passing parameters in batches
  • Link the newly created object to a common prototype object

Factory extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends extends

class Child extends Parent{
    constructor(age,name){
      super(name)
      this.age = age;
    }
    sayAge(){
      console.log(this.age)
    }
}
const obj = new Child(18,'lili');
Copy the code

But remember, this is still and Java classes in the difference is very big, don’t confuse STH with STH else, just like some grammar but did more and more far away from the truth, because in the js object oriented, is the true object oriented, rather than face the class, create the object does not simply, without the help of a class literal can be simple, But syntactic simplifications are necessary to make it easier and friendlier to create homogeneous objects.

A prototype chain is a one-way list

Following the development principle of separation of concerns, you usually organize your logic in different objects. For example, if you have a utility object utils and a data object that is responsible for rendering data to the page, click the button and it will bring up the this.text copy.

const utils = { tip(){ alert(this.text) } } const data = { text:'111', } object.setProtoTypeof (data,utils) btn.onclick = ()=>{data.text = '222'; Data.tip () // popup 222} this is just an example, a real project would not be so stupid to write, 'utils.tip.call(data)' would actually do the job.Copy the code

After associating two objects with object.setPrototypeof (data,utils), a prototype chain is formed: data => utils. In this way, the prototype chain is a one-way list of objects linked together, and the next pointer is the __proto__ property. Method properties that can’t be found on their own are traversed through the chain. In this example, the tip method is called on data. If the tip method is not found, the util object of the next object in the prototype chain is searched. After finding it, the “this” in tip method refers to itself, so it can pop up its own text data.

What are the advantages of stereotype delegation over class inheritance

  • Performance. As we all know, JS is designed for a language that only runs in the browser at the beginning. Before the birth of Node, it has always belonged to a client language. The client language naturally needs a lower footprint, and the way of prototype delegation will save more memory overhead than the physical copy of Java classes.

  • Flexible. You know js is a dynamic language, one of the biggest characteristic is to use more flexible, object system design is dynamic enough to keep the language style is consistent, dynamic also are not necessarily good, of course, improper use will also be a disadvantage, such as in the example above is directly modify the prototype, the risk of error object method calls.

    Of course, the reason why JS made such a choice does not exclude the personal preference of the designer, the author Brendan Eich also publicly stated in a small range that he particularly does not like the Java class pattern, so he chose a more flexible prototype approach at the beginning of the design.

At the end

Hope that the above will be helpful to everyone to understand the object system in JS, some of the views in this paper are actually very controversial, I hope everyone to discuss enthusiastically, put forward different opinions. But need civilized communication, no brainless spraying…