Constructor, prototype, prototype chain in JS

In typical OOP languages (such as Java), there is the concept of a class, a class is the template of an object, an object is an instance of a class, but before ES6, JS did not have the concept of a class

1. There are three ways to create an object:

1. Object literals

let obj = {}
Copy the code

2,new Object()

let obj = new Object()
Copy the code

3. Custom constructors

function person (name, age) {
  this.name = name
  this.age = age
  this.sayName = function () {
    console.log(this.name)
  }
}
let p1 = new person('Jerry', 18)
Copy the code
2. Constructor

A constructor is a special function used to initialize an object, that is, to assign initial values to its member variables. It is always used with new. We can extract some common properties and methods from objects and encapsulate them in this function.

Note when using constructors:

1. The constructor is used to create a class of objects whose first letter is capitalized

2. Constructors are used with new

When executed, new does the following four things:

Create a new empty object in memory

2. Make this point to the new object

Execute the code inside the constructor to add properties and methods to the new object

4, return the new object (so no return is needed in the constructor)

Constructor members can be added, either to the constructor itself or to this inside the constructor. Members added either way become static members or instance members, respectively

  • Static member: A member added to the constructor itself that can only be accessed by the constructor itself
  • Instance member: An object member created inside a constructor that can only be accessed by the instantiated object
function Person(name, age) { this.name = name this.age = age this.sayName = function () { console.log(this.name) } } // Instance members are the members added inside the constructor via this: Let p1 = new Person('Jerry', 18) person. gender = 'male' // static member, Gender => Static member console.log(person.gender) //male => Static member console.log(p1.gender) // undefined => static member console.log(p1.gender) // undefined => Cannot be accessed through objectsCopy the code
3. Constructors

The constructor method is nice, but it can be a waste of memory

function Person(name, age) {
  this.name = name
  this.age = age
  this.sayName = function () {
    console.log(this.name)
  }
}
let p1 = new Person('Jerry', 18)
let p2 = new Person('Jack', 19)
console.log(p1.sayName === p2.sayName) // false
Copy the code

When creating instance objects, for simple data types, assign values directly. For complex data types, when creating instance objects p1, a separate space is allocated for the complex data type sayName method. When creating object P2, a separate space is allocated for the complex data type sayName method. Two Spaces are created to store the same function

We want all objects to use the same function to save memory. How do we do that?

4. Constructor prototype

Constructors The functions assigned by stereotypes are shared by all objects

Js specifies that each constructor has a Prototype property that points to another object. Prototype is an object whose properties and methods are all owned by the constructor.

function Person(name, age) {
  this.name = name
  this.age = age
}
Person.prototype.sayName = function () {
  console.log(this.name)
}
let p1 = new Person('Jerry', 18)
let p2 = new Person('Jack', 19)
console.log(p1.sayName()) // Jerry
console.log(p2.sayName()) // Jack
console.log(p1.sayName === p2.sayName)  // true
p1.__proto__ === Person.prototype // true
Copy the code

In general, common attributes are defined in constructors, and common methods are placed on prototype objects.

What is a prototype: an object that we also call prototype object

What is a prototype for: Shared methods

Object prototype __proto__

Each object has a __proto__ attribute that points to the prototype object constructor. Objects can use the properties and methods of the prototype object constructor because the object has a __proto__ prototype

  • The __proto__ object prototype is equivalent to the prototype object prototype
  • The __proto__ object prototype is meant to provide a direction, or a route, for object look-up mechanisms, but it is a nonstandard attribute and therefore cannot be used in actual development. It only points internally to the prototype object

6. The constructor function

Both proto and constructor objects have a constructor property inside. Constructor we call it a constructor because it refers to the constructor itself

Contructor is mainly used to record which constructor the object refers to, and it can redirect the prototype object to the original constructor

Function Person(name, age) {this.name = name this.age = age} Person. Prototype = { You must manually refer back to the original constructor using constructor: Person, sayName: function () { } } let p1 = new Person('Jerry', 18) let p2 = new Person('Jack', 20) console.log(Person.prototype.constructor) console.log(p1.__proto__.constructor)Copy the code

Normally, the object’s methods are set in the constructor’s prototype object. If we have multiple object methods, we can assign the prototype object as an object, but this overwrites the original constructor object so that the modified prototype object constructor no longer points to the current constructor. At this point, we can add a constructor pointing to the original constructor in the modified prototype object

Relationships among constructors, instances, and prototype objects

8. Prototype chain

1, any object has a __proto__ prototype, pointing to the prototype object

2. The __proto__ prototype in the Person prototype Object points to Object.prototype

Prototype __proto__ is null. If it is an Object, there is a prototype __proto__ in it. If it is a prototype Object, there is a __proto__ in it. The Object prototype Object also has a __proto__ in it, which points to null

To put it simply, each object has a prototype, and each prototype is an object, so the prototype has its own prototype, so that one ring links one ring to form a chain, which is called the prototype chain

9. Member lookup mechanism of Js (rules)

1. When accessing properties (including methods) of an object, first look up whether the object itself has the properties

2, if not, find its prototype (i.e. the prototype object __proto__ points to).

3. Find the prototype of the prototype Object if it hasn’t already

4, and so on until Object (null)

5. The point of __proto__ object archetypes is to provide a direction, or a route, for the object member lookup mechanism

10. The prototype object this points to

This in the constructor refers to the instance object

Inside the prototype object is a method, and the “this” in this method refers to the caller of this method, that is, the instance object. Depending on how this is called, it refers to our caller

Bind (), call(), apply() 1, call() method: call an object, that is, call a function, change this reference to the function. The main role is to implement inheritance

foo.call(thisArg, arg1,arg2,....)
Copy the code

2, the apply() method: calls a function, that is, the way the function is called, and changes the function’s this pointer

foo.apply(thisArg, [argArray])
Copy the code

ThisArg: Specifies this value when foo is run

ArgArray: The value passed must be contained in the array

The return value is the return value of the function, because it is the calling function

Var arr = [1,20,30,60] var Max = math.max. Apply (Math, arr) MaxCopy the code

3. The bind() method does not call the function, but can change the this reference inside the function

foo.bind(thisArg, arg1, arg2,.....)
Copy the code

ThisArg: Specifies this value when foo is run

Arg1, arg2: Other arguments to pass

Returns a copy of the original function modified by the specified this value and initialization argument, that is, the new function created after the original function changed this

var btn = document.querySelector('button'); btn.onclick = function() { this.diabled = true; Var that = this; SetTimeout (function() {setTimeout(function() {this.disabled = false; this.disabled = false; }.bind(this), 3000); // This refers to the object BTN}Copy the code

Conclusion:

  • Call () often does inheritance
  • Apply () is often associated with arrays
  • Bind () does not call a function immediately. If there is a function we do not need to call immediately, but we want to change the reference to this inside the function, we use bind().
11. Built-in objects

You can use prototype objects to extend custom methods on built-in objects, such as adding custom sums to arrays

Array.prototype.sum = function () {
  let sum = 0
  for (let i = 0; i < this.length; i++) {
    sum += this[i]
  }
  return sum
}
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(arr.sum())
console.log(Array.prototype)
Copy the code

Array.prototype = {}, array.prototype. XXX = function (){}.