Object-oriented programming

What is Object-oriented Programming Object-oriented programming is an idea that is often compared to procedural programming.

Process-oriented: analyze the steps needed to solve the problem, write corresponding functions to achieve each step, and call the functions in turn.

Object oriented: The object that constitutes the problem is broken down into various objects, not to achieve a specific step, but to describe the behavior of this thing in the current problem.

The characteristics of object-oriented programming: 1, encapsulation: let the object users do not consider the internal implementation, only consider the use of functions, the internal code is protected, only set aside some API for users to use. 3. Polymorphism: Different objects acting on the same operation produce different results. The idea of polymorphism is to separate what you want to do from who you want to do it

When is it appropriate to use object-oriented thinking: in a more complex problem, or when there are many parties, it can be very good to simplify the problem, better expansion and maintenance

Object oriented in JS

1. Objects contain properties and methods

2. How objects are created

The ordinary way

const Player = new Object(a); Player.color ="white";
Player.start = function () {
  console.log("White chess");
};
Copy the code

Disadvantages of factory approach: Object type cannot be recognized, for example Player type is Object only

function createdObject () {
    let newObj = new object()
    newObj.color = 'black'
    newObj.start = function(){}
    return newObj;
}
Copy the code

Disadvantages of the constructor approach: The properties and methods added by this always refer to the current object, so any properties and methods added by this are copied in memory at instantiation time, resulting in a waste of memory. Advantages: Changing properties and methods of one object does not affect other objects

function Obj(color) {
  this.color = color;
  this.start = function () {};
}
const whitePlayer = new Obj("white");
const blackPlayer = new Obj("black");
Copy the code

Disadvantages: The properties and methods added by this always refer to the current object, so any properties and methods added by this will be copied in memory during instantiation, resulting in wasted memory. Advantage: Start occupies only one copy of memory

function Obj(color) {
  this.color = color;
}
Obj.prototype.start = function () {};
const whitePlayer = new Obj("white");
const blackPlayer = new Obj("black");
Copy the code

The static approach is a property method bound to a constructor that needs to be accessed through it

function Obj(color) {
  this.color = color;
  if(! Obj.pageNo){ Obj.pageNo =0
  }
  Obj.pageNo++
}
const whitePlayer = new Obj("white");
const blackPlayer = new Obj("black");
Copy the code

Prototype and prototype chain

1. How to find the prototype object

function Player(color) {
  this.color = color;
}

Player.prototype.start = function () {
  console.log(color + "Chess");
};

const white = new Player("white");
const black = new Player("black");

console.log(black.__proto__);
console.log(Object.getPrototypeOf(black)); __proto__ can be obtained by object.getProtoTypeof
console.log(Player.prototype);
//black.__proto__ == Player.prototype
console.log(Player.__proto__); 
Copy the code

2. What does the new keyword do?

1A new object inherited from Player.prototype, p1/p2, is created2, p1._prop_=== player.prototype, p1._prop_ points to player.prototype3Will,thisPoint to newly created p1, P24Returns a new object4.1Returns if the constructor does not explicitly return a valuethis
   4.2If the constructor has an explicit return value of a primitive type, such as number,string, or Boolean, then it still returnsthis
   4.3If the constructor has an explicit return value, it is an object type, such as {a: 1}, returns the object {a: 1 }
Copy the code
// 1. Create Object obj with new Object()
// 2. Take the first argument, which is the constructor we pass in. Additionally, since Shift modifies the array, arguments is removed from the first argument
// 3. Point obj's prototype to the constructor so that obj can access properties in the constructor prototype
// 4. Use apply to change the reference of constructor this to the newly created object, so that obj can access the properties in constructor
// 5. Return obj
function objectFactory() {
  let obj = {};
  let Constructor = [].shift.call(arguments);
  obj.__proto__ = Constructor.prototype;
  let ret = Constructor.apply(obj, arguments);
  return typeof ret === "object" ? ret : obj;
}
Copy the code

3. What is the prototype chain?

When accessing a property of an object, it looks first at the property itself. If not, it looks at its __proto__ implicit prototype, that is, its constructor’s prototype. If not, it looks again at the constructor’s __proto__. This layer by layer lookup will form a chain structure, which we call a prototype chain.

function Player() {}

Player.prototype.name = 'xxx';

const p1 = new Player();

p1.name = 'p1';

console.log(p1.name);  //p1

delete p1.name;

console.log(p1.name); //xxx

delete Player.prototype.name;

console.log(p1.name); //undefined
Copy the code

inheritance

1. Prototype chain inheritance

function parent(){
    this.name='parentName'
}
parent.prototype.getName = function(){
    console.log(this.name)
}
function child(){}

// const Child = new child()
// Child._proto_ = child.prorotype
// child.prorotype._proto == parent.prorotype
child.prototype = new parent()
child.prototype.constructor = child;
const obj = new child()
obj.getName()
Copy the code

Implicit questions:

If an instance of an attribute is of a reference type, then all instances are affected

Constructor inheritance

Find a way to copy attributes and methods from parent to child instead of the prototype object \parent to prevent instances from being shared

function Parent(name, color) {
    this.name = name;
    this.color = color;
    this.actions = ['sing'.'jump'.'rap'];
    this.eat = function () {}}//Parent.apply(this); Solve the first problem of prototype chain inheritance
function Child(id) {
    Parent.apply(this.Array.prototype.slice.call(arguments.1));
    this.id = id
}

const c1 = new Child('c1'.'red');
const c2 = new Child('c2'.'white');

console.log(c1.eat === c2.eat);
Copy the code

Implicit questions:

If an attribute or method is inherited, it must be defined in a constructor. If a method is defined in a constructor, the method must be created once every instance is created

3. Combinatorial inheritance

Prototype inheritance implements basic inheritance. Properties and methods are stored in Prototype. Subclasses can be called directly, but properties of reference types are shared by all instances and cannot be passed as arguments. Constructor inheritance first solves two problems of stereotype chain inheritance, but multiple creation methods within a constructor deletion consume memory

function Parent(name, actions) {
    this.name = name;
    this.actions = actions;
}

Parent.prototype.getName = function () {
    console.log(this.name + 'getName called');
}

function Child(id) {
    Parent.apply(this.Array.from(arguments).slice(1)); // Call the constructor for the first time
    this.id = id
}

Child.prototype = new Parent(); // Call the constructor a second time
Child.prototype.constructor = Child;

const c1 = new Child(1.'c1'['eat']);
const c2 = new Child(2.'c2'['run']);
c1.getName()
c2.getName()
Copy the code

Implicit questions:

The constructor is called twice

3. Parasitic inheritance

function Parent(name, actions) {
    this.name = name;
    this.actions = actions;
}

Parent.prototype.getName = function () {
    console.log(this.name + 'getName called');
}

function Child(id) {
    Parent.apply(this.Array.from(arguments).slice(1)); // Call the constructor for the first time
    this.id = id
}

//Child.prototype = new Parent(); // Call the constructor a second time
// es5
// let TempFunction = function () {};
// TempFunction.prototype = Parent.prototype;
// Child.prototype = new TempFunction();
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

const c1 = new Child(1.'c1'['eat']);
const c2 = new Child(2.'c2'['run']);
c1.getName()
c2.getName()
Copy the code