This article was first published on my personal website: cherryblog.site

Weekend in-depth understanding of the next javascript object-oriented programming ideas, harvest quite a lot, feel object-oriented programming has so a little understanding of ~ very open sen

What is object-oriented programming

Vividly describe object-oriented concepts


Object orientation is to decompose the transaction that constitutes the problem into various objects. The purpose of establishing objects is not to complete a step, but to describe the behavior of something in the whole step of solving the problem.

The difference between object-oriented and procedural

Object oriented programming and process oriented are two different ideas, we often hear the comparison of the two, start programming, most should is to use the process oriented programming, but as we grow older, or the object-oriented programming thought is better ~ the object-oriented and process-oriented actually is not completely relative, is not completely independent. I think the main difference between object orientation and procedure orientation is that procedure orientation is mostly verb oriented and the way to solve the problem is to call different functions step by step in order. While object oriented is mainly based on nouns, the problem is abstracted out of concrete objects, and this object has its own attributes and methods, in solving the problem is to combine different objects together to use. So the nice thing about object orientation is that it’s more extensible and it eliminates the problem of code reuse.

  • Process oriented is to analyze the steps needed to solve the problem, and then use functions to implement these steps step by step, use when you can call one by one.
  • Object orientation is to decompose the transaction that constitutes the problem into various objects. The purpose of establishing objects is not to complete a step, but to describe the behavior of something in the whole step of solving the problem.

There is a zhihu high vote answer is very interesting, to share with you ~

Object oriented: dogs. Eat (shit) Face process: eat.(dog, shit)

Concrete implementation let’s look at the most classic “put the elephant in the refrigerator” this problem

A process-oriented solution

The answer to “put an elephant in the fridge” in procedural programming is well known in three steps:

  1. Open the door (of a refrigerator);
  2. Put in (a refrigerator, an elephant);
  3. Close the door (refrigerator).

    Object-oriented solution

  4. Refrigerator. Open the door ()
  5. Refrigerator. To fill (an elephant).
  6. Refrigerator. Close the door ()

It can be seen that the focus of object oriented and process oriented is different. Process oriented is based on verbs. To complete an event is to call different action functions in sequence. Object oriented is subject and predicate oriented. Think of subject and predicate as objects that have their own properties and methods. For example, the refrigerator has its own ID attribute and a way to open the door. Then you can call the refrigerator open door method and pass it a parameter elephant. Simple examples The benefits of object orientation and procedure orientation are not immediately apparent.

The renju example

For example, the process-oriented design approach is the first step to analyze the problem:

  1. Start the game
  2. The spots to go first
  3. Draw the picture
  4. Judge the winning or losing
  5. Turn an albino
  6. Draw the picture
  7. Judge the winning or losing
  8. Return to Step 2

Implement each of the above steps as a separate function, and the problem is solved.

And object – oriented design is from another idea to solve the problem. The whole backgammon can be divided into

  1. Black and white, the two sides behave exactly the same
  2. Checkerboard system, responsible for drawing the screen

The first type of object (player object) is responsible for receiving user input and notifying the second type of object (board object) of the changes in the layout of the pieces. The board object is responsible for displaying the changes on the screen when it receives the I changes of the pieces. At the same time, the third type of object (rule system) is used to determine the game.

It is clear that object orientation divides problems into functions, not steps. Drawing a board game is spread across multiple steps in a process-oriented design, and different drawing versions are likely to occur, as designers often make various simplifications to account for the actual situation. In object-oriented design, drawing can only appear in the checkerboard object, thus guaranteeing the unity of drawing.

The unity of functions ensures the extensibility of object-oriented design. For example, if I wanted to add the regret feature, if I wanted to change the process-oriented design, the sequence of steps from input to judgment to display would have to be changed, and even the sequence of steps would have to be drastically adjusted. If it is object-oriented, only change the checkerboard object on the line, the checkerboard system saves the black and white sides of the chess spectrum, simple backtracking can, and display and rule judgment do not take into account, at the same time the whole call order of the object function has no change, the change is only local.

For example, if I want to change this backgammon game to go, if you design for process, then the rules of backgammon are distributed in every corner of your program, and it is better to rewrite them. But if you started with object-oriented design, all you have to do is change the rule objects. Isn’t that the difference between gobang and Go? (Of course the board sizes also seem different, but do you think this is a problem? Just make a small change to the checkerboard object. The general steps of chess, on the other hand, haven’t changed at all from an object-oriented perspective.

Changes to achieve the needs of the local design, of course, people have enough experience, using the object cannot guarantee that your application is object oriented, beginner or poor programmers probably with object-oriented virtual line and face the reality of the process, so that the words and actions of so-called object-oriented program design is difficult to have good portability and scalability.

encapsulation

Object orientation has three main features: encapsulation, inheritance and polymorphism. For ES5, there is no concept of class, and due to the function-level scope of JS (variables inside a function cannot be accessed outside the function), we can simulate the concept of class. In ES5, a class actually holds the variable of a function, which has its own properties and methods. The process of putting attributes and methods together as a class is called encapsulation.

Encapsulation: Encapsulate objective things into abstract classes, hide the implementation details of properties and methods, and expose only interfaces.

Add by constructor

Javascript provides a Constructor pattern for initializing objects when they are created. Constructors are just ordinary functions with the following characteristics

  • Capitalize (it is recommended that constructors start with a capital, i.e. use a big camel, and non-constructors start with a lower case)
  • Internal usethis
  • usenewAn instance

Adding properties and methods through constructors is actually adding properties and methods through this. Because this always refers to the current object, properties and methods added by this are only added to the current object and are owned by the object itself. So when we instantiate a new object, the properties and methods referred to by this will be created accordingly, which will be copied in memory, resulting in a waste of memory.

function Cat(name,color){
        this.name = name;
        this.color = color;
        this.eat = function () {
            alert('Eat a mouse')}}Copy the code

Example generation:

var cat1 = new Cat('tom'.'red')Copy the code

The properties and methods defined by this are copied whenever we instantiate the object

Through prototype

Adding attributes and objects to a class using this would result in a waste of memory, so we wondered if there was a way to use a pointer to the same method used by the instantiated class. So, the prototype approach came to mind

Javascript states that each constructor has a Prototype property that points to another object. All properties and methods of this object are inherited by instances of the constructor. That is, properties and methods that don’t change can be added directly to the class’s Prototype object.

 functionThe name, color (Cat) {this. Name = name; This. Color = color; } the prototype. Type ="Felines."; Cat.prototype.eat =function(){alert("Eat a mouse.")};Copy the code

And then generate the instance

var cat1 = new Cat("Heavy hair"."Yellow"); var cat2 = new Cat("二毛"."Black"); alert(cat1.type); // cat1.eat(); / / to eat miceCopy the code

In this case, the type attribute and the eat() method of all instances are actually the same memory address, pointing to the Prototype object, thus making the operation more efficient.

Pass outside the class. Syntax to add

We can also pass outside the class. Syntax is added because when instantiating an object, it is not executed to pass outside the class. Properties added by the syntax, so the instantiated object is not accessible. Objects and attributes added by the syntax can only be accessed through this class.

The difference between the three

Through constructors, stereotypes, and. All three can add attributes and methods to a class. But there are certain differences between the three. Constructor: Properties and methods added through this always refer to the current object, so properties and methods added through this are copied in memory at instantiation time, resulting in a waste of memory. But the advantage of this creation is that if you change the properties or methods of one object, it doesn’t affect the other objects (because each object is a copy). Prototype: The prototype inheritance method is not self-contained, we have to look up the prototype chain layer by layer. The advantage of this method is that we only create objects in memory once, and all instantiated objects point to the prototype object. However, there are disadvantages of this method because the instantiated objects point to the same memory address. Changing the properties of one object may affect other objects. Syntax: Passes outside the class. Properties and methods created by the syntax are created only once, but the instantiated objects created thus are not accessible, only through the class itself

Javascript also has private public protected

The keywords private public protected should be familiar to Java programmers. However, there is no such keyword in JS, but we want to define properties and methods that have certain access restrictions. So we can simulate private public protected access. If you are not familiar with Java, you may not be familiar with the concept of private public protected

  • Public: public indicates that the data member and member function are open to all users and can be directly invoked by all users
  • Private property is not allowed to be used by anyone other than the class itself.
  • Protected: For children and friends, protected is public and can be used without restriction. For other external classes, protected becomes private.

Js in private

Because of the nature of javascript’s function-level scope (properties and methods defined in functions are not accessible from the outside world), properties and methods we define directly inside functions are private.

The public in js

When instantiated with the new keyword, properties and variables defined by this are copied over, so properties and methods defined by this are public. Properties created by Prototype are also accessible to the class’s instantiated object after the class’s instantiation and are therefore public.

Protected in js

Inside the function, we can access some of the class’s private properties and methods through this method, and initialize some of the object’s properties at instantiation time.

The essence of the new

Var o = new Object() var o = new Object()

  1. Create a new object o
  2. o. __proto__ = Object.prototypeOf the newly created object__proto__Property pointing to the constructorprototype
  3. Point this to the newly created object
  4. Returns a new object, but we need to see if the constructor returns a value, if the constructor returns a primitive data typestring,boolean,number,null,undefinedIf the constructor returns an object type, then the new object is returned

Chestnut ~

var Book = function(id, name, price) {//private(id, name, price) var num = 1; var id = id;function checkId() {
            console.log('private'} //protected(you can access the private properties and methods inside the function. After instantiation, you can initialize the class to get the private properties of the function.) this.getName =function () {
            console.log(id)
        }
        this.getPrice = function() {console.log(price)} //public(after instantiation, the instantiated object can access ~) this.name = name; this.copy =function () {
            console.log('this is public'}} / / on the prototype of the Book after added methods instantiation can be instantiated object inheritance Book. The prototype. ProFunction =function () {
        console.log('this is proFunction'} // pass outside the function. Properties and methods created by the syntax can only be accessed through this class. Book.settime = is not accessible to instantiated objectsfunction () {
        console.log('this is new time')
    }
    var book1 = new Book('111'.Les Miserables.'$99') book1.getName(); Book1.checkid (); book1.checkid (); book1.checkid (); Book1. CheckId is not afunctionConsole. log(book1.id) // Undefined id is defined internally and is private, so the instantiated object cannot access console.log(book1.name) //name is created through this, Copy () //this is public book1.profunction (); //this is proFunction Book.setTime(); //this is new time book1.setTime(); Book1. setTime is not afunctionCopy the code

inheritance

Inheritance: Subclasses can use all of the functionality of their parent class and extend those functionality. The process of inheritance is the process of going from general to particular.

In fact, inheritance is based on the three characteristics of the encapsulation method.

Class type inheritance

Class inheritance is the use of a stereotype, adding methods to the stereotype of the parent class, which is then an instantiated object of the parent class.

// Declare the SuperClass var SuperClass =function () {
        var id = 1;
        this.name = ['javascript'];
        this.superValue = function () {
            console.log('superValue is true'); console.log(id) } }; / / for the parent class to add a total of SuperClass method. The prototype. GetSuperValue =function () {
        returnthis.superValue(); }; // Declare SubClass var SubClass =function () {
        this.subValue = function () {
            console.log('this is subValue ')}}; Prototype = new SuperClass(); / / add method to SubClass ttf_subclass. Prototype. GetSubValue =function () {
        return this.subValue()
    };

    var sub = new SubClass();
    var sub2 =  new  SubClass();

    sub.getSuperValue();   //superValue is true
    sub.getSubValue();     //this is subValue

    console.log(sub.id);    //undefined
    console.log(sub.name);  //javascript

    sub.name.push('java'); / / /"javascript"]
    console.log(sub2.name)  //["javascript"."java"]Copy the code

Subclass.prototype = new SuperClass(); The prototype object is used to add common methods to the prototype of the class, but the class cannot access these methods directly. After the class is instantiated, the newly created object copies the attributes and methods in the parent constructor and points __proto__ to the prototype object of the parent class. In this way, the subclass can access the public and protected properties and methods of the parent class, while the private properties and methods of the parent class are not inherited by the subclass.

Typing on the blackboard, as in the last paragraph of the code above, uses the method of class inheritance. If the parent class has a reference type in its constructor, it is shared by all instances in the subclass, so if an instance of one subclass changes the reference type, it affects other instances of the subclass. Here’s a quick question: why does changing a reference type in one subclass affect other subclass instances? What is a reference type in javascript, and what is the difference between a reference type and any other type?

Constructor inheritance

Superclass.call (this,id) changes the direction of this directly, so that the attributes and methods created by this are copied in the subclass. Since this is copied separately, each instantiated subclass does not affect each other. But it can cause memory waste problem

// Constructor inherits // declare the parent classfunction SuperClass(id) {
        var name = 'javascript'
        this.books=['javascript'.'html'.'css']; This. Id = id} / / declare the SuperClass SuperClass. The prototype method. The prototype showBooks =function() {console.log(this.books)} // Declare subclassesfunctionSubClass(id) {superclass.call (this,id)} var SubClass = new SubClass(10); var subclass2 = new SubClass(11); console.log(subclass1.books); console.log(subclass2.id); console.log(subclass1.name); //undefined subclass2.showBooks();Copy the code

Combinatorial inheritance

Let’s start by summarizing the pros and cons of class and constructor inheritance

Class inheritance Constructor inheritance
core idea The prototype of a subclass is an object instantiated by its parent class SuperClass.call(this,id)
advantages Subclasses instantiate objects with properties and methods that point to the parent class’s prototype Each instantiated subclass does not affect each other
disadvantages Subclasses may influence each other Memory is a waste of

So composite inheritance takes the best of both worlds, avoiding memory waste and making each instantiated subclass irrelevant.

// Declare the SuperClass var SuperClass =function (name) {
        this.name = name;
        this.books=['javascript'.'html'.'css']}; / / declare the SuperClass method on the prototype SuperClass. The prototype. ShowBooks =function() { console.log(this.books) }; // Declare SubClass var SubClass =function(name) { SuperClass.call(this, name) }; Prototype = new SuperClass(); // Prototype = new SuperClass(); Var subclass1 = new SubClass('java');
    var subclass2 = new SubClass('php');
    subclass2.showBooks();
    subclass1.books.push('ios'); / / /"javascript"."html"."css"] console.log(subclass1.books); / / /"javascript"."html"."css"."ios"] console.log(subclass2.books); / / /"javascript"."html"."css"]Copy the code

Parasitic combinatorial inheritance

Combinatorial inheritance is great, but it causes a problem where the parent constructor is created twice (once for call() and again for new), so parasitic combinatorial inheritance is introduced to solve this problem. The point is that the constructor of the parent class is created twice in a combination of class inheritance and constructor inheritance, but in class inheritance we don’t need to create the constructor of the parent class, we just need to subclass the prototype of the parent class. Create a copy of the parent class’s prototype, modify the constructor property, and set the parent class’s prototype

// Primitive inheritance is the encapsulation of class inheritance, which returns an instance whose prototype inherits the passed O objectfunctionInheritObject (o) {// Declare a transition function objectfunction F() {} // The prototype of the transition object inherits the parent object f.prototype = o; // Returns an instance of a transition object whose prototype inherits the parent objectreturnnew F(); } // Parasitic inheritance is the second encapsulation of stereotype inheritance, making the stereotype of a subclass equal to the stereotype of its parent class. The second encapsulation extends the inherited objectfunctionVar p = inheritPrototype(superClass. Prototype); P.constructor = subClass; // Set subClass. Prototype = p; } // Define the SuperClass var SuperClass =function (name) {
        this.name = name;
        this.books = ['javascript'.'html'.'css']}; / / define the SuperClass SuperClass. The prototype method. The prototype getBooks =function() { console.log(this.books) }; // SubClass var SubClass =function (name) {
        SuperClass.call(this,name)
    }

    inheritPrototype(SubClass,SuperClass);

    var subclass1 = new SubClass('php')Copy the code