Object-oriented (OOP)

One hallmark of object-oriented languages is the concept of classes, through which you can create any number of objects with the same properties and methods.

First of all, how do we understand the concept of objects? My understanding of an object is that an object is a simple abstraction of a single object, and an object is a Conntainer containing properties & methods. So what are attributes? What is the method? Properties refer to: the state of an object; Methods refer to the behavior of objects. Secondly, object-oriented characteristics: high code reusable, highly modular, flexible logical migration.

Constructor -> Generate object

Class is object template, JS is not based on class in nature, but based on constructor & prototype chainCopy the code
// Write the compatibility constructor
function Person(name, age) {
    const _isClass = this instanceof Person
    if( !_isClass ) {
        return new Person(name, age)
    }
    this.name = name
    this.age = age
}
const phil = Person('phil'.25)  //{name: "phil", age: 25}
Copy the code

Notice the new operator used above, what exactly does new do?

    1. Creates an empty object as the returned object instance
    1. Points the generated object’s prototype to the constructor’s Prototype property
    1. Gives the current instance object to the inner this
    1. Execute the constructor initialization code

What are the drawbacks of constructors?

As mentioned above, constructors include properties and methods. When you use an instance of a method in a constructor, each instance has its own method on its prototype, even though the method has no logic of its own, which wastes memory. This brings us to another important concept in JS ---- prototypes and prototype chains!Copy the code

Prototype and prototype chain

Prototype object: Person.prototype. Whenever a new function is created, a prototype property is created for that function according to a specific set of rules. This property points to the function’s prototype object. The example above, the Person has pointed to the prototype object prototype, and Person. The prototype. The constructor refers back to the Person.

inheritance

All properties and methods in the prototype object can be shared by the instance

In JS inheritance, mainly depends on the prototype chain to achieve.Copy the code

Prototype chain inheritance

function Person(){
    this.name = 'phil';
    this.habby = ['singing'.'playing'.'dancing']}function Chinese(){}
// Implement inheritance through an instance of Person. The essence of the implementation is to override the prototype object
Chinese.prototype = new Person()
const instance1 = new Chinese()
const instance2 = new Chinese()
instance1.habby.push('swimming')
// Drawbacks: ① If instance1.habby.push('swimming'),instance2's habby property is also affected
// Noise, i.e., reference-type data sharing on the prototype chain, leads to data contamination. ② Parameters cannot be passed
Copy the code

Constructor inheritance

The basic idea is simple: call the parent type’s constructor inside the subtype’s constructor

function Person(name){
    this.name = name
}

function Chinese(. args){
    Person.call(this. args) }// This solves the problem of using the prototype chain to implement inheritance without passing parameters
// Drawbacks: Methods are defined in constructors, so function reuse is out of the question
Copy the code

Combination of inheritance

Combines the advantages of both stereotype chain and constructor inheritance

function Person(name){
    this.name = name
}

function Chinese(. args){
    Person.call(this. args) }// The constructor of chinese. prototype was overwritten, resulting in the Chinese instance's constructor pointing to Person
Chinese.prototype = new Person()
// Rewrite to point an instance of Chinese to Chinese itself
Chinese.prototype.constructor = Chinese
// Drawbacks: Calling the constructor once when new Person() and a second time when person.call wastes performance.
Copy the code

Parasitic combination inheritance (currently the most common inheritance method)

The so-called parasitic combinatorial inheritance inherits properties through constructor inheritance and methods through a hybrid form of stereotype chains. The basic idea is that instead of calling the parent type’s constructor to specify the child type’s stereotype, all we need is a copy of the parent type’s stereotype

function Person(name){
    this.name = name
}

function Chinese(. args){
    Person.call(this. args) }// object.create () creates an empty Object whose prototype points to Person.prototype
Chinese.prototype = Object.create(Person.prototype)
Chinese.prototype.constructor = Chinese
Copy the code

Object.create

Extra: multiple inheritance (a method in which a class inherits more than one class)

function Person(name){
    this.name = name
}

function Chinese(skin){
    this.skin = skin
}

function ShangHai(name, ... args) {
    Person.call(this, name)
    Chinese.call(this. args) } ShangHai.prototype =Object.create(Person.prototype)
Object.assign(ShangHai.prototype, Chinese.prototype)
ShangHai.prototype.constructor = ShangHai
const a = new ShangHai('phil'.'yellow') // {name: "phil", skin: "yellow "}
Copy the code

This pointer

This object is bound at runtime based on the execution environment of the function: in a global function, this refers to the window; When a function is called as a method of an object, this refers to that object.

Implicit binding

  • 1. This points up the call stack
  • 2. If the function is globally isolated, point to window
  • 3. When a function is executed, the context points to the upper level if the function is called by the upper level
  • SetTimeout (function(){console.log(this)}, 100) {this is a window.
  • 5. Arrow functions in ES6 do not have this pointing problem.

Explicitly bound

By explicit binding, I mean using call, apply, and bind

Similarity: Both can change this point to difference: 2) Bind returns a new function that will not be executed immediately after call and applyCopy the code

Hand write a bind

// bind will return a new function; This function does not execute immediately; The ginseng unchanged
Function.prototype.MBind = function(){
   const _this = this
   const args = Array.from(arguments)
   const newThis = args.shift()
   return function(){
       return _this.apply(newThis, args)
   }
}
Copy the code

Apply’s reference-multipass parameter marshalling

  const arr = [1.2.3.4]
  Math.max.apply(this, arr) / / 4
  // Reflect provided in ES6 can also achieve the same effect
  Reflect.apply(Math.max, this, arr)
Copy the code

Priority: New > Explicit > Implicit > Global

Closure: A function that has access to variables inside the scope of another function.

One point to make here is that unlike this, the scope is defined at the time of the declaration, whereas this is known at the time of the call. Common scenario 1: Functions as return values

    function person(){
        let name = 'phil'
        return function(){
            console.log(name)
        }
    }
    let someone = person()
    someone() // 'phil'
 // Have access to values outside the function scope
Copy the code

Common scenario 2: Functions as parameters

function Animal(fn){
    let color = 'yellow'
    fn()
}
function cat(){
    let color
    console.log(color) // undefined
}
Animal(cat) 
// This proves that the scope is defined when a function is declared, regardless of where or how it is executed.
Copy the code